mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
3278 Kusto Unit Tests - Part 1 (#1057)
* 3278 Added unit tests in MetadataFactoryTests and Microsoft.Kusto.ServiceLayer.UnitTests project * 3278 Removed todo and changed unit test to validate megabytes * 3278 Added file and unit tests in AutoCompleteHelperTests.cs * 3278 Removed unused functions from Kusto > ScriptAsScriptingOperation * 3278 Added unit tests for DataSourceFactory * 3278 Refactored AdminService to pass in ConnectionService rather than through instance variable. Added unit test for AdminServiceTests * 3278 Refactored DataSourceFactory to not have static functions for future unit tests * 3278 Re-added properties that were flagged as unused but are being used by ADS in ReliableDataSourceConnection.cs * 3278 Re-added properties that were flagged as unused but are being used by ADS in ReliableDataSourceConnection.cs * adding pipeline to execute tests (#1062) * 3278 Converted GetDefaultAutoComplete and GetDefaultSemanticMarkers to static functions in DataSourceFactory. Removed unused constructor in ScriptFile. Added positive unit tests for both functions * undoing release version bump * adding additional configs * adressing feedback * Correcting path in csproj Co-authored-by: Jorge Berumen <52225468+joberume@users.noreply.github.com> Co-authored-by: joberume <jberumen3@miners.utep.edu>
This commit is contained in:
@@ -36,5 +36,7 @@ install:
|
|||||||
script:
|
script:
|
||||||
- dotnet build src/Microsoft.SqlTools.ServiceLayer
|
- dotnet build src/Microsoft.SqlTools.ServiceLayer
|
||||||
- dotnet test test/Microsoft.SqlTools.ServiceLayer.UnitTests
|
- 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 build src/Microsoft.SqlTools.CoreServices
|
||||||
- dotnet test test/Microsoft.SqlTools.Hosting.UnitTests
|
- dotnet test test/Microsoft.SqlTools.Hosting.UnitTests
|
||||||
@@ -17,10 +17,12 @@ before_build:
|
|||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- dotnet build src/Microsoft.SqlTools.ServiceLayer
|
- dotnet build src/Microsoft.SqlTools.ServiceLayer
|
||||||
|
- dotnet build src/Microsoft.Kusto.ServiceLayer
|
||||||
- dotnet build src/Microsoft.SqlTools.CoreServices
|
- dotnet build src/Microsoft.SqlTools.CoreServices
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- dotnet test test/Microsoft.SqlTools.ServiceLayer.UnitTests
|
- dotnet test test/Microsoft.SqlTools.ServiceLayer.UnitTests
|
||||||
|
- dotnet test test/Microsoft.Kusto.ServiceLayer.UnitTests
|
||||||
- dotnet test test/Microsoft.SqlTools.Hosting.UnitTests
|
- dotnet test test/Microsoft.SqlTools.Hosting.UnitTests
|
||||||
|
|
||||||
after_test:
|
after_test:
|
||||||
|
|||||||
@@ -45,17 +45,35 @@ steps:
|
|||||||
projects: '$(Build.SourcesDirectory)/src/Microsoft.SqlTools.ServiceLayer'
|
projects: '$(Build.SourcesDirectory)/src/Microsoft.SqlTools.ServiceLayer'
|
||||||
arguments: '--configfile $(Build.SourcesDirectory)/nuget.config'
|
arguments: '--configfile $(Build.SourcesDirectory)/nuget.config'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@1
|
||||||
|
displayName: 'dotnet restore src/Microsoft.Kusto.ServiceLayer'
|
||||||
|
inputs:
|
||||||
|
command: restore
|
||||||
|
projects: '$(Build.SourcesDirectory)/src/Microsoft.Kusto.ServiceLayer'
|
||||||
|
arguments: '--configfile $(Build.SourcesDirectory)/nuget.config'
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: DotNetCoreCLI@2
|
||||||
displayName: 'dotnet build src/Microsoft.SqlTools.ServiceLayer'
|
displayName: 'dotnet build src/Microsoft.SqlTools.ServiceLayer'
|
||||||
inputs:
|
inputs:
|
||||||
projects: '$(Build.SourcesDirectory)/src/Microsoft.SqlTools.ServiceLayer'
|
projects: '$(Build.SourcesDirectory)/src/Microsoft.SqlTools.ServiceLayer'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: 'dotnet build src/Microsoft.Kusto.ServiceLayer'
|
||||||
|
inputs:
|
||||||
|
projects: '$(Build.SourcesDirectory)/src/Microsoft.Kusto.ServiceLayer'
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: DotNetCoreCLI@2
|
||||||
displayName: 'dotnet build src/Microsoft.SqlTools.ServiceLayer --configuration Release'
|
displayName: 'dotnet build src/Microsoft.SqlTools.ServiceLayer --configuration Release'
|
||||||
inputs:
|
inputs:
|
||||||
projects: '$(Build.SourcesDirectory)/src/Microsoft.SqlTools.ServiceLayer '
|
projects: '$(Build.SourcesDirectory)/src/Microsoft.SqlTools.ServiceLayer '
|
||||||
arguments: '--configuration Release'
|
arguments: '--configuration Release'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: 'dotnet build src/Microsoft.Kusto.ServiceLayer --configuration Release'
|
||||||
|
inputs:
|
||||||
|
projects: '$(Build.SourcesDirectory)/src/Microsoft.Kusto.ServiceLayer '
|
||||||
|
arguments: '--configuration Release'
|
||||||
|
|
||||||
- task: BatchScript@1
|
- task: BatchScript@1
|
||||||
displayName: 'Run script build.cmd'
|
displayName: 'Run script build.cmd'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -69,6 +87,12 @@ steps:
|
|||||||
command: restore
|
command: restore
|
||||||
projects: test/Microsoft.SqlTools.ServiceLayer.UnitTests
|
projects: test/Microsoft.SqlTools.ServiceLayer.UnitTests
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@1
|
||||||
|
displayName: 'dotnet restore test/Microsoft.Kusto.ServiceLayer.UnitTests'
|
||||||
|
inputs:
|
||||||
|
command: restore
|
||||||
|
projects: test/Microsoft.Kusto.ServiceLayer.UnitTests
|
||||||
|
|
||||||
- task: DotNetCoreCLI@1
|
- task: DotNetCoreCLI@1
|
||||||
displayName: 'dotnet test test/Microsoft.SqlTools.ServiceLayer.UnitTests'
|
displayName: 'dotnet test test/Microsoft.SqlTools.ServiceLayer.UnitTests'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -76,6 +100,13 @@ steps:
|
|||||||
projects: test/Microsoft.SqlTools.ServiceLayer.UnitTests
|
projects: test/Microsoft.SqlTools.ServiceLayer.UnitTests
|
||||||
arguments: '--logger "trx;LogFileName=xunit.trx"'
|
arguments: '--logger "trx;LogFileName=xunit.trx"'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@1
|
||||||
|
displayName: 'dotnet test test/Microsoft.Kusto.ServiceLayer.UnitTests'
|
||||||
|
inputs:
|
||||||
|
command: test
|
||||||
|
projects: test/Microsoft.Kusto.ServiceLayer.UnitTests
|
||||||
|
arguments: '--logger "trx;LogFileName=xunit.trx"'
|
||||||
|
|
||||||
- task: Npm@1
|
- task: Npm@1
|
||||||
displayName: 'npm install -g gulp-cli'
|
displayName: 'npm install -g gulp-cli'
|
||||||
inputs:
|
inputs:
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
"TestProjects": {
|
"TestProjects": {
|
||||||
"Microsoft.SqlTools.ServiceLayer.UnitTests": [
|
"Microsoft.SqlTools.ServiceLayer.UnitTests": [
|
||||||
"netcoreapp3.1"
|
"netcoreapp3.1"
|
||||||
|
],
|
||||||
|
"Microsoft.Kusto.ServiceLayer.UnitTests": [
|
||||||
|
"netcoreapp3.1"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Frameworks": [
|
"Frameworks": [
|
||||||
@@ -18,7 +21,8 @@
|
|||||||
"MainProjects": [
|
"MainProjects": [
|
||||||
"Microsoft.SqlTools.Credentials",
|
"Microsoft.SqlTools.Credentials",
|
||||||
"Microsoft.SqlTools.ResourceProvider",
|
"Microsoft.SqlTools.ResourceProvider",
|
||||||
"Microsoft.SqlTools.ServiceLayer"
|
"Microsoft.SqlTools.ServiceLayer",
|
||||||
|
"Microsoft.Kusto.ServiceLayer"
|
||||||
],
|
],
|
||||||
"PackageProjects": [
|
"PackageProjects": [
|
||||||
"Microsoft.SqlTools.CoreServices",
|
"Microsoft.SqlTools.CoreServices",
|
||||||
|
|||||||
@@ -112,6 +112,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azure-pipelines", "azure-pi
|
|||||||
azure-pipelines\release.yml = azure-pipelines\release.yml
|
azure-pipelines\release.yml = azure-pipelines\release.yml
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Kusto.ServiceLayer.UnitTests", "test\Microsoft.Kusto.ServiceLayer.UnitTests\Microsoft.Kusto.ServiceLayer.UnitTests.csproj", "{AFCDED82-B659-4BE1-86ED-0F4F8BC661AE}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -257,6 +259,12 @@ Global
|
|||||||
{E0C941C8-91F2-4BE1-8B79-AC88EDB78729}.Integration|Any CPU.Build.0 = Debug|Any CPU
|
{E0C941C8-91F2-4BE1-8B79-AC88EDB78729}.Integration|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{E0C941C8-91F2-4BE1-8B79-AC88EDB78729}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{E0C941C8-91F2-4BE1-8B79-AC88EDB78729}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{E0C941C8-91F2-4BE1-8B79-AC88EDB78729}.Release|Any CPU.Build.0 = Release|Any CPU
|
{E0C941C8-91F2-4BE1-8B79-AC88EDB78729}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AFCDED82-B659-4BE1-86ED-0F4F8BC661AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AFCDED82-B659-4BE1-86ED-0F4F8BC661AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AFCDED82-B659-4BE1-86ED-0F4F8BC661AE}.Integration|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AFCDED82-B659-4BE1-86ED-0F4F8BC661AE}.Integration|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AFCDED82-B659-4BE1-86ED-0F4F8BC661AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AFCDED82-B659-4BE1-86ED-0F4F8BC661AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -287,6 +295,7 @@ Global
|
|||||||
{D3696EFA-FB1E-4848-A726-FF7B168AFB96} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
|
{D3696EFA-FB1E-4848-A726-FF7B168AFB96} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
|
||||||
{0EC2B30C-0652-49AE-9594-85B3C3E9CA21} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
|
{0EC2B30C-0652-49AE-9594-85B3C3E9CA21} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
|
||||||
{E0C941C8-91F2-4BE1-8B79-AC88EDB78729} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
|
{E0C941C8-91F2-4BE1-8B79-AC88EDB78729} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
|
||||||
|
{AFCDED82-B659-4BE1-86ED-0F4F8BC661AE} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {B31CDF4B-2851-45E5-8C5F-BE97125D9DD8}
|
SolutionGuid = {B31CDF4B-2851-45E5-8C5F-BE97125D9DD8}
|
||||||
|
|||||||
@@ -21,50 +21,28 @@ namespace Microsoft.Kusto.ServiceLayer.Admin
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class AdminService
|
public class AdminService
|
||||||
{
|
{
|
||||||
private static readonly Lazy<AdminService> instance = new Lazy<AdminService>(() => new AdminService());
|
private static readonly Lazy<AdminService> _instance = new Lazy<AdminService>(() => new AdminService());
|
||||||
|
|
||||||
private static ConnectionService connectionService = null;
|
private static ConnectionService _connectionService;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Internal for testing purposes only
|
|
||||||
/// </summary>
|
|
||||||
internal static ConnectionService ConnectionServiceInstance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (AdminService.connectionService == null)
|
|
||||||
{
|
|
||||||
AdminService.connectionService = ConnectionService.Instance;
|
|
||||||
}
|
|
||||||
return AdminService.connectionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
AdminService.connectionService = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the singleton instance object
|
/// Gets the singleton instance object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static AdminService Instance
|
public static AdminService Instance => _instance.Value;
|
||||||
{
|
|
||||||
get { return instance.Value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the service instance
|
/// Initializes the service instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void InitializeService(ServiceHost serviceHost)
|
public void InitializeService(ServiceHost serviceHost, ConnectionService connectionService)
|
||||||
{
|
{
|
||||||
serviceHost.SetRequestHandler(GetDatabaseInfoRequest.Type, HandleGetDatabaseInfoRequest);
|
serviceHost.SetRequestHandler(GetDatabaseInfoRequest.Type, HandleGetDatabaseInfoRequest);
|
||||||
|
_connectionService = connectionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle get database info request
|
/// Handle get database info request
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal async Task HandleGetDatabaseInfoRequest(
|
private async Task HandleGetDatabaseInfoRequest(
|
||||||
GetDatabaseInfoParams databaseParams,
|
GetDatabaseInfoParams databaseParams,
|
||||||
RequestContext<GetDatabaseInfoResponse> requestContext)
|
RequestContext<GetDatabaseInfoResponse> requestContext)
|
||||||
{
|
{
|
||||||
@@ -72,10 +50,7 @@ namespace Microsoft.Kusto.ServiceLayer.Admin
|
|||||||
{
|
{
|
||||||
Func<Task> requestHandler = async () =>
|
Func<Task> requestHandler = async () =>
|
||||||
{
|
{
|
||||||
ConnectionInfo connInfo;
|
_connectionService.TryFindConnection(databaseParams.OwnerUri, out var connInfo);
|
||||||
AdminService.ConnectionServiceInstance.TryFindConnection(
|
|
||||||
databaseParams.OwnerUri,
|
|
||||||
out connInfo);
|
|
||||||
DatabaseInfo info = null;
|
DatabaseInfo info = null;
|
||||||
|
|
||||||
if (connInfo != null)
|
if (connInfo != null)
|
||||||
@@ -106,13 +81,18 @@ namespace Microsoft.Kusto.ServiceLayer.Admin
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connInfo"></param>
|
/// <param name="connInfo"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal DatabaseInfo GetDatabaseInfo(ConnectionInfo connInfo)
|
public DatabaseInfo GetDatabaseInfo(ConnectionInfo connInfo)
|
||||||
{
|
{
|
||||||
if(!string.IsNullOrEmpty(connInfo.ConnectionDetails.DatabaseName)){
|
if (string.IsNullOrEmpty(connInfo.ConnectionDetails.DatabaseName))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
ReliableDataSourceConnection connection;
|
ReliableDataSourceConnection connection;
|
||||||
connInfo.TryGetConnection("Default", out connection);
|
connInfo.TryGetConnection("Default", out connection);
|
||||||
IDataSource dataSource = connection.GetUnderlyingConnection();
|
IDataSource dataSource = connection.GetUnderlyingConnection();
|
||||||
DataSourceObjectMetadata objectMetadata = MetadataFactory.CreateClusterMetadata(connInfo.ConnectionDetails.ServerName);
|
DataSourceObjectMetadata objectMetadata =
|
||||||
|
MetadataFactory.CreateClusterMetadata(connInfo.ConnectionDetails.ServerName);
|
||||||
|
|
||||||
List<DataSourceObjectMetadata> metadata = dataSource.GetChildObjects(objectMetadata, true).ToList();
|
List<DataSourceObjectMetadata> metadata = dataSource.GetChildObjects(objectMetadata, true).ToList();
|
||||||
var databaseMetadata = metadata.Where(o => o.Name == connInfo.ConnectionDetails.DatabaseName);
|
var databaseMetadata = metadata.Where(o => o.Name == connInfo.ConnectionDetails.DatabaseName);
|
||||||
@@ -121,8 +101,5 @@ namespace Microsoft.Kusto.ServiceLayer.Admin
|
|||||||
|
|
||||||
return databaseInfo.ElementAtOrDefault(0);
|
return databaseInfo.ElementAtOrDefault(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
|
|
||||||
private ConcurrentDictionary<string, IConnectedBindingQueue> connectedQueues = new ConcurrentDictionary<string, IConnectedBindingQueue>();
|
private ConcurrentDictionary<string, IConnectedBindingQueue> connectedQueues = new ConcurrentDictionary<string, IConnectedBindingQueue>();
|
||||||
|
|
||||||
|
private IDataSourceFactory _dataSourceFactory;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Map from script URIs to ConnectionInfo objects
|
/// Map from script URIs to ConnectionInfo objects
|
||||||
/// This is internal for testing access only
|
/// This is internal for testing access only
|
||||||
@@ -397,7 +399,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
DataSourceObjectMetadata clusterMetadata = MetadataFactory.CreateClusterMetadata(connectionInfo.ConnectionDetails.ServerName);
|
DataSourceObjectMetadata clusterMetadata = MetadataFactory.CreateClusterMetadata(connectionInfo.ConnectionDetails.ServerName);
|
||||||
|
|
||||||
DiagnosticsInfo clusterDiagnostics = dataSource.GetDiagnostics(clusterMetadata);
|
DiagnosticsInfo clusterDiagnostics = dataSource.GetDiagnostics(clusterMetadata);
|
||||||
ReliableConnectionHelper.ServerInfo serverInfo = DataSourceFactory.ConvertToServerinfoFormat(DataSourceType.Kusto, clusterDiagnostics);
|
ReliableConnectionHelper.ServerInfo serverInfo = DataSourceFactory.ConvertToServerInfoFormat(DataSourceType.Kusto, clusterDiagnostics);
|
||||||
|
|
||||||
response.ServerInfo = new ServerInfo
|
response.ServerInfo = new ServerInfo
|
||||||
{
|
{
|
||||||
@@ -789,10 +791,11 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void InitializeService(IProtocolEndpoint serviceHost, IDataSourceConnectionFactory dataSourceConnectionFactory,
|
public void InitializeService(IProtocolEndpoint serviceHost, IDataSourceConnectionFactory dataSourceConnectionFactory,
|
||||||
IConnectedBindingQueue connectedBindingQueue)
|
IConnectedBindingQueue connectedBindingQueue, IDataSourceFactory dataSourceFactory)
|
||||||
{
|
{
|
||||||
ServiceHost = serviceHost;
|
ServiceHost = serviceHost;
|
||||||
_dataSourceConnectionFactory = dataSourceConnectionFactory;
|
_dataSourceConnectionFactory = dataSourceConnectionFactory;
|
||||||
|
_dataSourceFactory = dataSourceFactory;
|
||||||
|
|
||||||
connectedQueues.AddOrUpdate("Default", connectedBindingQueue, (key, old) => connectedBindingQueue);
|
connectedQueues.AddOrUpdate("Default", connectedBindingQueue, (key, old) => connectedBindingQueue);
|
||||||
LockedDatabaseManager.ConnectionService = this;
|
LockedDatabaseManager.ConnectionService = this;
|
||||||
@@ -1411,7 +1414,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
string connectionString = BuildConnectionString(connInfo.ConnectionDetails);
|
string connectionString = BuildConnectionString(connInfo.ConnectionDetails);
|
||||||
|
|
||||||
// TODOKusto: Pass in type of DataSource needed to make this generic. Hard coded to Kusto right now.
|
// TODOKusto: Pass in type of DataSource needed to make this generic. Hard coded to Kusto right now.
|
||||||
return DataSourceFactory.Create(DataSourceType.Kusto, connectionString, connInfo.ConnectionDetails.AzureAccountToken);
|
return _dataSourceFactory.Create(DataSourceType.Kusto, connectionString, connInfo.ConnectionDetails.AzureAccountToken);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,14 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
[Export(typeof(IDataSourceConnectionFactory))]
|
[Export(typeof(IDataSourceConnectionFactory))]
|
||||||
public class DataSourceConnectionFactory : IDataSourceConnectionFactory
|
public class DataSourceConnectionFactory : IDataSourceConnectionFactory
|
||||||
{
|
{
|
||||||
|
private readonly IDataSourceFactory _dataSourceFactory;
|
||||||
|
|
||||||
|
[ImportingConstructor]
|
||||||
|
public DataSourceConnectionFactory(IDataSourceFactory dataSourceFactory)
|
||||||
|
{
|
||||||
|
_dataSourceFactory = dataSourceFactory;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new SqlConnection object
|
/// Creates a new SqlConnection object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -24,7 +32,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
{
|
{
|
||||||
RetryPolicy connectionRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy();
|
RetryPolicy connectionRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy();
|
||||||
RetryPolicy commandRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy();
|
RetryPolicy commandRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy();
|
||||||
return new ReliableDataSourceConnection(connectionString, connectionRetryPolicy, commandRetryPolicy, azureAccountToken);
|
return new ReliableDataSourceConnection(connectionString, connectionRetryPolicy, commandRetryPolicy, azureAccountToken, _dataSourceFactory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Composition;
|
||||||
using Microsoft.Kusto.ServiceLayer.Utility;
|
using Microsoft.Kusto.ServiceLayer.Utility;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||||
using Microsoft.Kusto.ServiceLayer.DataSource.DataSourceIntellisense;
|
using Microsoft.Kusto.ServiceLayer.DataSource.DataSourceIntellisense;
|
||||||
@@ -9,9 +10,10 @@ using Microsoft.Kusto.ServiceLayer.LanguageServices.Completion;
|
|||||||
|
|
||||||
namespace Microsoft.Kusto.ServiceLayer.DataSource
|
namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||||
{
|
{
|
||||||
public class DataSourceFactory
|
[Export(typeof(IDataSourceFactory))]
|
||||||
|
public class DataSourceFactory : IDataSourceFactory
|
||||||
{
|
{
|
||||||
public static IDataSource Create(DataSourceType dataSourceType, string connectionString, string azureAccountToken)
|
public IDataSource Create(DataSourceType dataSourceType, string connectionString, string azureAccountToken)
|
||||||
{
|
{
|
||||||
ValidationUtils.IsArgumentNotNullOrWhiteSpace(connectionString, nameof(connectionString));
|
ValidationUtils.IsArgumentNotNullOrWhiteSpace(connectionString, nameof(connectionString));
|
||||||
ValidationUtils.IsArgumentNotNullOrWhiteSpace(azureAccountToken, nameof(azureAccountToken));
|
ValidationUtils.IsArgumentNotNullOrWhiteSpace(azureAccountToken, nameof(azureAccountToken));
|
||||||
@@ -57,15 +59,16 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReliableConnectionHelper.ServerInfo ConvertToServerinfoFormat(DataSourceType dataSourceType, DiagnosticsInfo clusterDiagnostics)
|
public static ReliableConnectionHelper.ServerInfo ConvertToServerInfoFormat(DataSourceType dataSourceType, DiagnosticsInfo clusterDiagnostics)
|
||||||
{
|
{
|
||||||
switch (dataSourceType)
|
switch (dataSourceType)
|
||||||
{
|
{
|
||||||
case DataSourceType.Kusto:
|
case DataSourceType.Kusto:
|
||||||
{
|
{
|
||||||
ReliableConnectionHelper.ServerInfo serverInfo = new ReliableConnectionHelper.ServerInfo();
|
return new ReliableConnectionHelper.ServerInfo
|
||||||
serverInfo.Options = new Dictionary<string, object>(clusterDiagnostics.Options);
|
{
|
||||||
return serverInfo;
|
Options = new Dictionary<string, object>(clusterDiagnostics.Options)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||||
|
{
|
||||||
|
public interface IDataSourceFactory
|
||||||
|
{
|
||||||
|
IDataSource Create(DataSourceType dataSourceType, string connectionString, string azureAccountToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
|
|
||||||
private readonly string _connectionString;
|
private readonly string _connectionString;
|
||||||
private readonly string _azureAccountToken;
|
private readonly string _azureAccountToken;
|
||||||
|
private readonly IDataSourceFactory _dataSourceFactory;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the ReliableKustoClient class with a given connection string
|
/// Initializes a new instance of the ReliableKustoClient class with a given connection string
|
||||||
@@ -52,11 +53,15 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
/// <param name="connectionString">The connection string used to open the SQL Azure database.</param>
|
/// <param name="connectionString">The connection string used to open the SQL Azure database.</param>
|
||||||
/// <param name="connectionRetryPolicy">The retry policy defining whether to retry a request if a connection fails to be established.</param>
|
/// <param name="connectionRetryPolicy">The retry policy defining whether to retry a request if a connection fails to be established.</param>
|
||||||
/// <param name="commandRetryPolicy">The retry policy defining whether to retry a request if a command fails to be executed.</param>
|
/// <param name="commandRetryPolicy">The retry policy defining whether to retry a request if a command fails to be executed.</param>
|
||||||
public ReliableDataSourceConnection(string connectionString, RetryPolicy connectionRetryPolicy, RetryPolicy commandRetryPolicy, string azureAccountToken)
|
/// <param name="azureAccountToken"></param>
|
||||||
|
/// <param name="dataSourceFactory"></param>
|
||||||
|
public ReliableDataSourceConnection(string connectionString, RetryPolicy connectionRetryPolicy,
|
||||||
|
RetryPolicy commandRetryPolicy, string azureAccountToken, IDataSourceFactory dataSourceFactory)
|
||||||
{
|
{
|
||||||
_connectionString = connectionString;
|
_connectionString = connectionString;
|
||||||
_azureAccountToken = azureAccountToken;
|
_azureAccountToken = azureAccountToken;
|
||||||
_dataSource = DataSourceFactory.Create(DataSourceType.Kusto, connectionString, azureAccountToken);
|
_dataSourceFactory = dataSourceFactory;
|
||||||
|
_dataSource = dataSourceFactory.Create(DataSourceType.Kusto, connectionString, azureAccountToken);
|
||||||
|
|
||||||
_connectionRetryPolicy = connectionRetryPolicy ?? RetryPolicyFactory.CreateNoRetryPolicy();
|
_connectionRetryPolicy = connectionRetryPolicy ?? RetryPolicyFactory.CreateNoRetryPolicy();
|
||||||
_commandRetryPolicy = commandRetryPolicy ?? RetryPolicyFactory.CreateNoRetryPolicy();
|
_commandRetryPolicy = commandRetryPolicy ?? RetryPolicyFactory.CreateNoRetryPolicy();
|
||||||
@@ -116,6 +121,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
/// Gets the policy which decides whether to retry a connection request, based on how many
|
/// 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.
|
/// times the request has been made and the reason for the last failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// ReSharper disable once UnusedMember.Global
|
||||||
public RetryPolicy ConnectionRetryPolicy
|
public RetryPolicy ConnectionRetryPolicy
|
||||||
{
|
{
|
||||||
get { return _connectionRetryPolicy; }
|
get { return _connectionRetryPolicy; }
|
||||||
@@ -125,6 +131,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
/// Gets the policy which decides whether to retry a command, based on how many
|
/// 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.
|
/// times the request has been made and the reason for the last failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// ReSharper disable once UnusedMember.Global
|
||||||
public RetryPolicy CommandRetryPolicy
|
public RetryPolicy CommandRetryPolicy
|
||||||
{
|
{
|
||||||
get { return _commandRetryPolicy; }
|
get { return _commandRetryPolicy; }
|
||||||
@@ -145,6 +152,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the server name from the underlying connection.
|
/// Gets the server name from the underlying connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// ReSharper disable once UnusedMember.Global
|
||||||
public string ClusterName
|
public string ClusterName
|
||||||
{
|
{
|
||||||
get { return _dataSource.ClusterName; }
|
get { return _dataSource.ClusterName; }
|
||||||
@@ -182,7 +190,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
{
|
{
|
||||||
_connectionRetryPolicy.ExecuteAction(() =>
|
_connectionRetryPolicy.ExecuteAction(() =>
|
||||||
{
|
{
|
||||||
_dataSource = DataSourceFactory.Create(DataSourceType.Kusto, _connectionString, _azureAccountToken);
|
_dataSource = _dataSourceFactory.Create(DataSourceType.Kusto, _connectionString, _azureAccountToken);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,6 +232,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
/// Gets the time to wait while trying to establish a connection before terminating
|
/// Gets the time to wait while trying to establish a connection before terminating
|
||||||
/// the attempt and generating an error.
|
/// the attempt and generating an error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// ReSharper disable once UnusedMember.Global
|
||||||
public int ConnectionTimeout
|
public int ConnectionTimeout
|
||||||
{
|
{
|
||||||
get { return 30; }
|
get { return 30; }
|
||||||
@@ -237,14 +246,6 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
{
|
{
|
||||||
get { return _dataSource.DatabaseName; }
|
get { return _dataSource.DatabaseName; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VerifyConnectionOpen(ReliableDataSourceConnection conn)
|
|
||||||
{
|
|
||||||
if(conn.GetUnderlyingConnection() == null)
|
|
||||||
{
|
|
||||||
conn.Open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ namespace Microsoft.Kusto.ServiceLayer
|
|||||||
var scripter = serviceProvider.GetService<IScripter>();
|
var scripter = serviceProvider.GetService<IScripter>();
|
||||||
var dataSourceConnectionFactory = serviceProvider.GetService<IDataSourceConnectionFactory>();
|
var dataSourceConnectionFactory = serviceProvider.GetService<IDataSourceConnectionFactory>();
|
||||||
var connectedBindingQueue = serviceProvider.GetService<IConnectedBindingQueue>();
|
var connectedBindingQueue = serviceProvider.GetService<IConnectedBindingQueue>();
|
||||||
|
var dataSourceFactory = serviceProvider.GetService<IDataSourceFactory>();
|
||||||
|
|
||||||
// Initialize and register singleton services so they're accessible for any MEF service. In the future, these
|
// Initialize and register singleton services so they're accessible for any MEF service. In the future, these
|
||||||
// could be updated to be IComposableServices, which would avoid the requirement to define a singleton instance
|
// could be updated to be IComposableServices, which would avoid the requirement to define a singleton instance
|
||||||
@@ -78,10 +79,10 @@ namespace Microsoft.Kusto.ServiceLayer
|
|||||||
WorkspaceService<SqlToolsSettings>.Instance.InitializeService(serviceHost);
|
WorkspaceService<SqlToolsSettings>.Instance.InitializeService(serviceHost);
|
||||||
serviceProvider.RegisterSingleService(WorkspaceService<SqlToolsSettings>.Instance);
|
serviceProvider.RegisterSingleService(WorkspaceService<SqlToolsSettings>.Instance);
|
||||||
|
|
||||||
LanguageService.Instance.InitializeService(serviceHost, connectedBindingQueue);
|
LanguageService.Instance.InitializeService(serviceHost, connectedBindingQueue, dataSourceFactory);
|
||||||
serviceProvider.RegisterSingleService(LanguageService.Instance);
|
serviceProvider.RegisterSingleService(LanguageService.Instance);
|
||||||
|
|
||||||
ConnectionService.Instance.InitializeService(serviceHost, dataSourceConnectionFactory, connectedBindingQueue);
|
ConnectionService.Instance.InitializeService(serviceHost, dataSourceConnectionFactory, connectedBindingQueue, dataSourceFactory);
|
||||||
serviceProvider.RegisterSingleService(ConnectionService.Instance);
|
serviceProvider.RegisterSingleService(ConnectionService.Instance);
|
||||||
|
|
||||||
CredentialService.Instance.InitializeService(serviceHost);
|
CredentialService.Instance.InitializeService(serviceHost);
|
||||||
@@ -90,10 +91,10 @@ namespace Microsoft.Kusto.ServiceLayer
|
|||||||
QueryExecutionService.Instance.InitializeService(serviceHost);
|
QueryExecutionService.Instance.InitializeService(serviceHost);
|
||||||
serviceProvider.RegisterSingleService(QueryExecutionService.Instance);
|
serviceProvider.RegisterSingleService(QueryExecutionService.Instance);
|
||||||
|
|
||||||
ScriptingService.Instance.InitializeService(serviceHost, scripter);
|
ScriptingService.Instance.InitializeService(serviceHost, scripter, dataSourceFactory);
|
||||||
serviceProvider.RegisterSingleService(ScriptingService.Instance);
|
serviceProvider.RegisterSingleService(ScriptingService.Instance);
|
||||||
|
|
||||||
AdminService.Instance.InitializeService(serviceHost);
|
AdminService.Instance.InitializeService(serviceHost, ConnectionService.Instance);
|
||||||
serviceProvider.RegisterSingleService(AdminService.Instance);
|
serviceProvider.RegisterSingleService(AdminService.Instance);
|
||||||
|
|
||||||
MetadataService.Instance.InitializeService(serviceHost);
|
MetadataService.Instance.InitializeService(serviceHost);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
{
|
{
|
||||||
internal const int DefaultBindingTimeout = 500;
|
internal const int DefaultBindingTimeout = 500;
|
||||||
private readonly ISqlConnectionOpener _connectionOpener;
|
private readonly ISqlConnectionOpener _connectionOpener;
|
||||||
|
private readonly IDataSourceFactory _dataSourceFactory;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current settings
|
/// Gets the current settings
|
||||||
@@ -34,9 +35,10 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
}
|
}
|
||||||
|
|
||||||
[ImportingConstructor]
|
[ImportingConstructor]
|
||||||
public ConnectedBindingQueue(ISqlConnectionOpener sqlConnectionOpener)
|
public ConnectedBindingQueue(ISqlConnectionOpener sqlConnectionOpener, IDataSourceFactory dataSourceFactory)
|
||||||
{
|
{
|
||||||
_connectionOpener = sqlConnectionOpener;
|
_connectionOpener = sqlConnectionOpener;
|
||||||
|
_dataSourceFactory = dataSourceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -160,7 +162,7 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
bindingContext.ServerConnection = _connectionOpener.OpenServerConnection(connInfo, featureName);
|
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);
|
||||||
|
|
||||||
if (needMetadata)
|
if (needMetadata)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <param name="dataSourceFactory"></param>
|
/// <param name="dataSourceFactory"></param>
|
||||||
/// <param name="connectedBindingQueue"></param>
|
/// <param name="connectedBindingQueue"></param>
|
||||||
public void InitializeService(ServiceHost serviceHost, IConnectedBindingQueue connectedBindingQueue)
|
public void InitializeService(ServiceHost serviceHost, IConnectedBindingQueue connectedBindingQueue, IDataSourceFactory dataSourceFactory)
|
||||||
{
|
{
|
||||||
_bindingQueue = connectedBindingQueue;
|
_bindingQueue = connectedBindingQueue;
|
||||||
// Register the requests that this service will handle
|
// Register the requests that this service will handle
|
||||||
@@ -854,7 +854,7 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
if (scriptParseInfo == null)
|
if (scriptParseInfo == null)
|
||||||
{
|
{
|
||||||
var scriptDocInfo = ScriptDocumentInfo.CreateDefaultDocumentInfo(textDocumentPosition, scriptFile);
|
var scriptDocInfo = ScriptDocumentInfo.CreateDefaultDocumentInfo(textDocumentPosition, scriptFile);
|
||||||
resultCompletionItems = resultCompletionItems = DataSourceFactory.GetDefaultAutoComplete(DataSourceType.Kusto, scriptDocInfo, textDocumentPosition.Position); //TODO_KUSTO: DataSourceFactory.GetDefaultAutoComplete 1st param should get the datasource type generically instead of hard coded DataSourceType.Kusto
|
resultCompletionItems = DataSourceFactory.GetDefaultAutoComplete(DataSourceType.Kusto, scriptDocInfo, textDocumentPosition.Position); //TODO_KUSTO: DataSourceFactory.GetDefaultAutoComplete 1st param should get the datasource type generically instead of hard coded DataSourceType.Kusto
|
||||||
return resultCompletionItems;
|
return resultCompletionItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ using Microsoft.Kusto.ServiceLayer.DataSource;
|
|||||||
using Microsoft.SqlTools.Utility;
|
using Microsoft.SqlTools.Utility;
|
||||||
using Microsoft.SqlServer.Management.Common;
|
using Microsoft.SqlServer.Management.Common;
|
||||||
using Microsoft.SqlServer.Management.Smo;
|
using Microsoft.SqlServer.Management.Smo;
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Text;
|
|
||||||
using System.Globalization;
|
|
||||||
using Microsoft.SqlServer.Management.SqlScriptPublish;
|
using Microsoft.SqlServer.Management.SqlScriptPublish;
|
||||||
using Microsoft.Kusto.ServiceLayer.Utility;
|
|
||||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
@@ -28,19 +24,10 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
{
|
{
|
||||||
private readonly IScripter _scripter;
|
private readonly IScripter _scripter;
|
||||||
private static readonly Dictionary<string, SqlServerVersion> scriptCompatibilityMap = LoadScriptCompatibilityMap();
|
private static readonly Dictionary<string, SqlServerVersion> scriptCompatibilityMap = LoadScriptCompatibilityMap();
|
||||||
/// <summary>
|
|
||||||
/// Left delimiter for an named object
|
|
||||||
/// </summary>
|
|
||||||
public const char LeftDelimiter = '[';
|
|
||||||
|
|
||||||
/// <summary>
|
public ScriptAsScriptingOperation(ScriptingParams parameters, string azureAccountToken, IScripter scripter, IDataSourceFactory dataSourceFactory) : base(parameters, dataSourceFactory)
|
||||||
/// right delimiter for a named object
|
|
||||||
/// </summary>
|
|
||||||
public const char RightDelimiter = ']';
|
|
||||||
|
|
||||||
public ScriptAsScriptingOperation(ScriptingParams parameters, string azureAccountToken, IScripter scripter) : base(parameters)
|
|
||||||
{
|
{
|
||||||
DataSource = DataSourceFactory.Create(DataSourceType.Kusto, this.Parameters.ConnectionString,
|
DataSource = _dataSourceFactory.Create(DataSourceType.Kusto, this.Parameters.ConnectionString,
|
||||||
azureAccountToken);
|
azureAccountToken);
|
||||||
_scripter = scripter;
|
_scripter = scripter;
|
||||||
}
|
}
|
||||||
@@ -177,200 +164,6 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generate a schema qualified name (e.g. [schema].[objectName]) for an object if the option for SchemaQualify is true
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="schema">The schema name. May be null or empty in which case it will be ignored</param>
|
|
||||||
/// <param name="objectName">The object name.</param>
|
|
||||||
/// <param name="schemaQualify">Whether to schema qualify the object or not</param>
|
|
||||||
/// <returns>The object name, quoted as appropriate and schema-qualified if the option is set</returns>
|
|
||||||
private static string GenerateSchemaQualifiedName(string schema, string objectName, bool schemaQualify)
|
|
||||||
{
|
|
||||||
var qualifiedName = new StringBuilder();
|
|
||||||
|
|
||||||
if (schemaQualify && !String.IsNullOrEmpty(schema))
|
|
||||||
{
|
|
||||||
// schema.name
|
|
||||||
qualifiedName.AppendFormat(CultureInfo.InvariantCulture, "{0}.{1}", GetDelimitedString(schema), GetDelimitedString(objectName));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// name
|
|
||||||
qualifiedName.AppendFormat(CultureInfo.InvariantCulture, "{0}", GetDelimitedString(objectName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return qualifiedName.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// getting delimited string
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="str">string</param>
|
|
||||||
/// <returns>string</returns>
|
|
||||||
static private string GetDelimitedString(string str)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(str))
|
|
||||||
{
|
|
||||||
return String.Empty;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StringBuilder qualifiedName = new StringBuilder();
|
|
||||||
qualifiedName.AppendFormat("{0}{1}{2}",
|
|
||||||
LeftDelimiter,
|
|
||||||
QuoteObjectName(str),
|
|
||||||
RightDelimiter);
|
|
||||||
return qualifiedName.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// turn a smo datatype object into a type that can be inserted into tsql, e.g. nvarchar(20)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type"></param>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static string GetDatatype(DataType type, ScriptingOptions options)
|
|
||||||
{
|
|
||||||
// string we'll return.
|
|
||||||
string rv = string.Empty;
|
|
||||||
|
|
||||||
string dataType = type.Name;
|
|
||||||
switch (type.SqlDataType)
|
|
||||||
{
|
|
||||||
// char, nchar, nchar, nvarchar, varbinary, nvarbinary are all displayed as type(length)
|
|
||||||
// length of -1 is taken to be type(max). max isn't localizable.
|
|
||||||
case SqlDataType.Char:
|
|
||||||
case SqlDataType.NChar:
|
|
||||||
case SqlDataType.VarChar:
|
|
||||||
case SqlDataType.NVarChar:
|
|
||||||
case SqlDataType.Binary:
|
|
||||||
case SqlDataType.VarBinary:
|
|
||||||
rv = string.Format(CultureInfo.InvariantCulture,
|
|
||||||
"{0}({1})",
|
|
||||||
dataType,
|
|
||||||
type.MaximumLength);
|
|
||||||
break;
|
|
||||||
case SqlDataType.VarCharMax:
|
|
||||||
case SqlDataType.NVarCharMax:
|
|
||||||
case SqlDataType.VarBinaryMax:
|
|
||||||
rv = string.Format(CultureInfo.InvariantCulture,
|
|
||||||
"{0}(max)",
|
|
||||||
dataType);
|
|
||||||
break;
|
|
||||||
// numeric and decimal are displayed as type precision,scale
|
|
||||||
case SqlDataType.Numeric:
|
|
||||||
case SqlDataType.Decimal:
|
|
||||||
rv = string.Format(CultureInfo.InvariantCulture,
|
|
||||||
"{0}({1},{2})",
|
|
||||||
dataType,
|
|
||||||
type.NumericPrecision,
|
|
||||||
type.NumericScale);
|
|
||||||
break;
|
|
||||||
//time, datetimeoffset and datetime2 are displayed as type scale
|
|
||||||
case SqlDataType.Time:
|
|
||||||
case SqlDataType.DateTimeOffset:
|
|
||||||
case SqlDataType.DateTime2:
|
|
||||||
rv = string.Format(CultureInfo.InvariantCulture,
|
|
||||||
"{0}({1})",
|
|
||||||
dataType,
|
|
||||||
type.NumericScale);
|
|
||||||
break;
|
|
||||||
// anything else is just type.
|
|
||||||
case SqlDataType.Xml:
|
|
||||||
if (type.Schema != null && type.Schema.Length > 0 && dataType != null && dataType.Length > 0)
|
|
||||||
{
|
|
||||||
rv = String.Format(CultureInfo.InvariantCulture
|
|
||||||
, "xml ({0}{2}{1}.{0}{3}{1})"
|
|
||||||
, LeftDelimiter
|
|
||||||
, RightDelimiter
|
|
||||||
, QuoteObjectName(type.Schema)
|
|
||||||
, QuoteObjectName(dataType));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rv = "xml";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SqlDataType.UserDefinedDataType:
|
|
||||||
case SqlDataType.UserDefinedTableType:
|
|
||||||
case SqlDataType.UserDefinedType:
|
|
||||||
//User defined types may be in a non-DBO schema so append it if necessary
|
|
||||||
rv = GenerateSchemaQualifiedName(type.Schema, dataType, options.SchemaQualify);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rv = dataType;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Double quotes certain characters in object name
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sqlObject"></param>
|
|
||||||
public static string QuoteObjectName(string sqlObject)
|
|
||||||
{
|
|
||||||
|
|
||||||
int len = sqlObject.Length;
|
|
||||||
StringBuilder result = new StringBuilder(sqlObject.Length);
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
if (sqlObject[i] == ']')
|
|
||||||
{
|
|
||||||
result.Append(']');
|
|
||||||
}
|
|
||||||
result.Append(sqlObject[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteUseDatabase(Database parentObject, StringBuilder stringBuilder , ScriptingOptions options)
|
|
||||||
{
|
|
||||||
if (options.IncludeDatabaseContext)
|
|
||||||
{
|
|
||||||
string useDb = string.Format(CultureInfo.InvariantCulture, "USE {0}", CommonConstants.DefaultBatchSeperator);
|
|
||||||
if (!options.NoCommandTerminator)
|
|
||||||
{
|
|
||||||
stringBuilder.Append(useDb);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stringBuilder.Append(useDb);
|
|
||||||
stringBuilder.Append(Environment.NewLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetScript(ScriptingOptions options, StringCollection stringCollection)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (var item in stringCollection)
|
|
||||||
{
|
|
||||||
sb.Append(item);
|
|
||||||
if (options != null && !options.NoCommandTerminator)
|
|
||||||
{
|
|
||||||
//Ensure the batch separator is always on a new line (to avoid syntax errors)
|
|
||||||
//but don't write an extra if we already have one as this can affect definitions
|
|
||||||
//of objects such as Stored Procedures (see TFS#9125366)
|
|
||||||
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}{2}",
|
|
||||||
item.EndsWith(Environment.NewLine) ? string.Empty : Environment.NewLine,
|
|
||||||
CommonConstants.DefaultBatchSeperator,
|
|
||||||
Environment.NewLine);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.AppendFormat(CultureInfo.InvariantCulture, Environment.NewLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private UrnCollection CreateUrns(IDataSource dataSource)
|
private UrnCollection CreateUrns(IDataSource dataSource)
|
||||||
{
|
{
|
||||||
IEnumerable<ScriptingObject> selectedObjects = new List<ScriptingObject>(this.Parameters.ScriptingObjects);
|
IEnumerable<ScriptingObject> selectedObjects = new List<ScriptingObject>(this.Parameters.ScriptingObjects);
|
||||||
@@ -533,27 +326,5 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
scriptingOptions.AnsiPadding = true;
|
scriptingOptions.AnsiPadding = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ScripterScriptingError(object sender, ScriptingErrorEventArgs e)
|
|
||||||
{
|
|
||||||
this.CancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
Logger.Write(
|
|
||||||
TraceEventType.Verbose,
|
|
||||||
string.Format(
|
|
||||||
"Sending scripting error progress event, Urn={0}, OperationId={1}, Completed={2}, Error={3}",
|
|
||||||
e.Current,
|
|
||||||
this.OperationId,
|
|
||||||
false,
|
|
||||||
e?.InnerException?.ToString() ?? "null"));
|
|
||||||
|
|
||||||
this.SendProgressNotificationEvent(new ScriptingProgressNotificationParams
|
|
||||||
{
|
|
||||||
ScriptingObject = e.Current?.ToScriptingObject(),
|
|
||||||
Status = "Failed",
|
|
||||||
ErrorMessage = e?.InnerException?.Message,
|
|
||||||
ErrorDetails = e?.InnerException?.ToString(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
|
|
||||||
private string azureAccessToken;
|
private string azureAccessToken;
|
||||||
|
|
||||||
public ScriptingScriptOperation(ScriptingParams parameters, string azureAccessToken) : base(parameters)
|
public ScriptingScriptOperation(ScriptingParams parameters, string azureAccessToken, IDataSourceFactory dataSourceFactory) : base(parameters, dataSourceFactory)
|
||||||
{
|
{
|
||||||
this.azureAccessToken = azureAccessToken;
|
this.azureAccessToken = azureAccessToken;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
private bool disposed;
|
private bool disposed;
|
||||||
|
|
||||||
private IScripter _scripter;
|
private IScripter _scripter;
|
||||||
|
private IDataSourceFactory _dataSourceFactory;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Internal for testing purposes only
|
/// Internal for testing purposes only
|
||||||
@@ -66,9 +67,10 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serviceHost"></param>
|
/// <param name="serviceHost"></param>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
public void InitializeService(ServiceHost serviceHost, IScripter scripter)
|
public void InitializeService(ServiceHost serviceHost, IScripter scripter, IDataSourceFactory dataSourceFactory)
|
||||||
{
|
{
|
||||||
_scripter = scripter;
|
_scripter = scripter;
|
||||||
|
_dataSourceFactory = dataSourceFactory;
|
||||||
serviceHost.SetRequestHandler(ScriptingRequest.Type, this.HandleScriptExecuteRequest);
|
serviceHost.SetRequestHandler(ScriptingRequest.Type, this.HandleScriptExecuteRequest);
|
||||||
serviceHost.SetRequestHandler(ScriptingCancelRequest.Type, this.HandleScriptCancelRequest);
|
serviceHost.SetRequestHandler(ScriptingCancelRequest.Type, this.HandleScriptCancelRequest);
|
||||||
serviceHost.SetRequestHandler(ScriptingListObjectsRequest.Type, this.HandleListObjectsRequest);
|
serviceHost.SetRequestHandler(ScriptingListObjectsRequest.Type, this.HandleListObjectsRequest);
|
||||||
@@ -131,11 +133,11 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
|
|
||||||
if (!ShouldCreateScriptAsOperation(parameters))
|
if (!ShouldCreateScriptAsOperation(parameters))
|
||||||
{
|
{
|
||||||
operation = new ScriptingScriptOperation(parameters, accessToken);
|
operation = new ScriptingScriptOperation(parameters, accessToken, _dataSourceFactory);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
operation = new ScriptAsScriptingOperation(parameters, accessToken, _scripter);
|
operation = new ScriptAsScriptingOperation(parameters, accessToken, _scripter, _dataSourceFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
operation.PlanNotification += (sender, e) => requestContext.SendEvent(ScriptingPlanNotificationEvent.Type, e).Wait();
|
operation.PlanNotification += (sender, e) => requestContext.SendEvent(ScriptingPlanNotificationEvent.Type, e).Wait();
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
// 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 Microsoft.SqlServer.Management.Common;
|
|
||||||
using Microsoft.Kusto.ServiceLayer.Connection;
|
|
||||||
using Microsoft.Kusto.ServiceLayer.Scripting.Contracts;
|
using Microsoft.Kusto.ServiceLayer.Scripting.Contracts;
|
||||||
using Microsoft.Kusto.ServiceLayer.DataSource;
|
using Microsoft.Kusto.ServiceLayer.DataSource;
|
||||||
using Microsoft.SqlTools.Utility;
|
using Microsoft.SqlTools.Utility;
|
||||||
@@ -22,10 +20,12 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class SmoScriptingOperation : ScriptingOperation
|
public abstract class SmoScriptingOperation : ScriptingOperation
|
||||||
{
|
{
|
||||||
|
protected readonly IDataSourceFactory _dataSourceFactory;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public SmoScriptingOperation(ScriptingParams parameters)
|
protected SmoScriptingOperation(ScriptingParams parameters, IDataSourceFactory dataSourceFactory)
|
||||||
{
|
{
|
||||||
|
_dataSourceFactory = dataSourceFactory;
|
||||||
Validate.IsNotNull("parameters", parameters);
|
Validate.IsNotNull("parameters", parameters);
|
||||||
|
|
||||||
this.Parameters = parameters;
|
this.Parameters = parameters;
|
||||||
@@ -77,7 +77,7 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
|
|||||||
{
|
{
|
||||||
string serverName = string.Empty;
|
string serverName = string.Empty;
|
||||||
|
|
||||||
using(var dataSource = DataSourceFactory.Create(DataSourceType.Kusto, connectionString, azureAccessToken))
|
using(var dataSource = _dataSourceFactory.Create(DataSourceType.Kusto, connectionString, azureAccessToken))
|
||||||
{
|
{
|
||||||
serverName = dataSource.ClusterName;
|
serverName = dataSource.ClusterName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,14 +98,6 @@ namespace Microsoft.Kusto.ServiceLayer.Workspace.Contracts
|
|||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add a default constructor for testing
|
|
||||||
/// </summary>
|
|
||||||
public ScriptFile()
|
|
||||||
{
|
|
||||||
ClientUri = "test.sql";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new ScriptFile instance by reading file contents from
|
/// Creates a new ScriptFile instance by reading file contents from
|
||||||
/// the given TextReader.
|
/// the given TextReader.
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
<ProjectReference Include="../Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" />
|
<ProjectReference Include="../Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" />
|
||||||
<ProjectReference Include="../Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj" />
|
<ProjectReference Include="../Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj" />
|
||||||
<ProjectReference Include="../Microsoft.SqlTools.ManagedBatchParser/Microsoft.SqlTools.ManagedBatchParser.csproj" />
|
<ProjectReference Include="../Microsoft.SqlTools.ManagedBatchParser/Microsoft.SqlTools.ManagedBatchParser.csproj" />
|
||||||
|
<ProjectReference Include="../Microsoft.Kusto.ServiceLayer/Microsoft.Kusto.ServiceLayer.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="$(PkgMicrosoft_SqlServer_DacFx)\lib\netstandard2.0\Microsoft.Data.Tools.Schema.SqlTasks.targets">
|
<Content Include="$(PkgMicrosoft_SqlServer_DacFx)\lib\netstandard2.0\Microsoft.Data.Tools.Schema.SqlTasks.targets">
|
||||||
@@ -48,20 +49,10 @@
|
|||||||
<!-- this target enables dependency files to be copied as part of the output of ProjectReference.
|
<!-- this target enables dependency files to be copied as part of the output of ProjectReference.
|
||||||
https://github.com/dotnet/sdk/issues/1675
|
https://github.com/dotnet/sdk/issues/1675
|
||||||
-->
|
-->
|
||||||
<Target Name="AddRuntimeDependenciesToContent"
|
<Target Name="AddRuntimeDependenciesToContent" Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" BeforeTargets="GetCopyToOutputDirectoryItems" DependsOnTargets="GenerateBuildDependencyFile;
 GenerateBuildRuntimeConfigurationFiles">
|
||||||
Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'"
|
|
||||||
BeforeTargets="GetCopyToOutputDirectoryItems"
|
|
||||||
DependsOnTargets="GenerateBuildDependencyFile;
|
|
||||||
GenerateBuildRuntimeConfigurationFiles">
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ContentWithTargetPath Include="$(ProjectDepsFilePath)"
|
<ContentWithTargetPath Include="$(ProjectDepsFilePath)" Condition="'$(GenerateDependencyFile)' == 'true'" CopyToOutputDirectory="PreserveNewest" TargetPath="$(ProjectDepsFileName)" />
|
||||||
Condition="'$(GenerateDependencyFile)' == 'true'"
|
<ContentWithTargetPath Include="$(ProjectRuntimeConfigFilePath)" Condition="'$(GenerateRuntimeConfigurationFiles)' == 'true'" CopyToOutputDirectory="PreserveNewest" TargetPath="$(ProjectRuntimeConfigFileName)" />
|
||||||
CopyToOutputDirectory="PreserveNewest"
|
|
||||||
TargetPath="$(ProjectDepsFileName)" />
|
|
||||||
<ContentWithTargetPath Include="$(ProjectRuntimeConfigFilePath)"
|
|
||||||
Condition="'$(GenerateRuntimeConfigurationFiles)' == 'true'"
|
|
||||||
CopyToOutputDirectory="PreserveNewest"
|
|
||||||
TargetPath="$(ProjectRuntimeConfigFileName)" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Microsoft.Kusto.ServiceLayer.Admin;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.Connection;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.Connection.Contracts;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace Microsoft.Kusto.ServiceLayer.UnitTests.Admin.Contracts
|
||||||
|
{
|
||||||
|
public class AdminServiceTests
|
||||||
|
{
|
||||||
|
[TestCase(null)]
|
||||||
|
[TestCase("")]
|
||||||
|
public void GetDatabaseInfo_Returns_Null_For_Invalid_DatabaseName(string databaseName)
|
||||||
|
{
|
||||||
|
var dataSourceConnectionFactory = new Mock<IDataSourceConnectionFactory>();
|
||||||
|
var connectionDetails = new ConnectionDetails
|
||||||
|
{
|
||||||
|
DatabaseName = databaseName
|
||||||
|
};
|
||||||
|
var connectionInfo = new ConnectionInfo(dataSourceConnectionFactory.Object, "", connectionDetails);
|
||||||
|
|
||||||
|
var adminService = new AdminService();
|
||||||
|
var databaseInfo = adminService.GetDatabaseInfo(connectionInfo);
|
||||||
|
Assert.IsNull(databaseInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.DataSource;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.DataSource.DataSourceIntellisense;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.LanguageServices.Completion;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.Workspace.Contracts;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace Microsoft.Kusto.ServiceLayer.UnitTests.DataSource
|
||||||
|
{
|
||||||
|
public class DataSourceFactoryTests
|
||||||
|
{
|
||||||
|
[TestCase(typeof(ArgumentNullException), "", "AzureAccountToken")]
|
||||||
|
[TestCase(typeof(ArgumentNullException), "ConnectionString", "")]
|
||||||
|
[TestCase(typeof(ArgumentException), "ConnectionString", "AzureAccountToken")]
|
||||||
|
public void Create_Throws_Exceptions_For_InvalidParams(Type exceptionType,
|
||||||
|
string connectionString,
|
||||||
|
string azureAccountToken)
|
||||||
|
{
|
||||||
|
var dataSourceFactory = new DataSourceFactory();
|
||||||
|
Assert.Throws(exceptionType,
|
||||||
|
() => dataSourceFactory.Create(DataSourceType.None, connectionString, azureAccountToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetDefaultAutoComplete_Throws_ArgumentException_For_InvalidDataSourceType()
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
DataSourceFactory.GetDefaultAutoComplete(DataSourceType.None, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetDefaultAutoComplete_Returns_CompletionItems()
|
||||||
|
{
|
||||||
|
var textDocumentPosition = new TextDocumentPosition
|
||||||
|
{
|
||||||
|
Position = new Position()
|
||||||
|
};
|
||||||
|
var scriptFile = new ScriptFile("", "", "");
|
||||||
|
var scriptParseInfo = new ScriptParseInfo();
|
||||||
|
var documentInfo = new ScriptDocumentInfo(textDocumentPosition, scriptFile, scriptParseInfo);
|
||||||
|
var position = new Position();
|
||||||
|
|
||||||
|
var completionItems = DataSourceFactory.GetDefaultAutoComplete(DataSourceType.Kusto, documentInfo, position);
|
||||||
|
Assert.AreNotEqual(0, completionItems.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetDefaultSemanticMarkers_Throws_ArgumentException_For_InvalidDataSourceType()
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
DataSourceFactory.GetDefaultSemanticMarkers(DataSourceType.None, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetDefaultSemanticMarkers_Returns_ScriptFileMarker()
|
||||||
|
{
|
||||||
|
var parseInfo = new ScriptParseInfo();
|
||||||
|
var file = new ScriptFile("", "", "");
|
||||||
|
var queryText = ".show databases";
|
||||||
|
|
||||||
|
var semanticMarkers = DataSourceFactory.GetDefaultSemanticMarkers(DataSourceType.Kusto, parseInfo, file, queryText);
|
||||||
|
|
||||||
|
Assert.AreNotEqual(0, semanticMarkers.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ConvertToServerInfoFormat_Throws_ArgumentException_For_InvalidDataSourceType()
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
DataSourceFactory.ConvertToServerInfoFormat(DataSourceType.None, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ConvertToServerInfoFormat_Returns_ServerInfo_With_Options()
|
||||||
|
{
|
||||||
|
var diagnosticsInfo = new DiagnosticsInfo
|
||||||
|
{
|
||||||
|
Options = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{"Key", "Object"}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var serverInfo = DataSourceFactory.ConvertToServerInfoFormat(DataSourceType.Kusto, diagnosticsInfo);
|
||||||
|
|
||||||
|
Assert.IsNotNull(serverInfo.Options);
|
||||||
|
Assert.AreEqual(diagnosticsInfo.Options["Key"], serverInfo.Options["Key"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.Metadata.Contracts;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace Microsoft.Kusto.ServiceLayer.UnitTests.DataSource.Metadata
|
||||||
|
{
|
||||||
|
public class MetadataFactoryTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void CreateClusterMetadata_ThrowsNullException_For_NullClusterName()
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentNullException>(() => MetadataFactory.CreateClusterMetadata(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[TestCase("")]
|
||||||
|
[TestCase(null)]
|
||||||
|
[TestCase(" ")]
|
||||||
|
public void CreateDatabaseMetadata_ThrowsNullException_For_InvalidDatabaseName(string databaseName)
|
||||||
|
{
|
||||||
|
var testMetadata = new DataSourceObjectMetadata
|
||||||
|
{
|
||||||
|
MetadataType = DataSourceMetadataType.Cluster
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.Throws<ArgumentNullException>(() => MetadataFactory.CreateDatabaseMetadata(testMetadata, databaseName));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CreateDatabaseMetadata_ThrowsNullException_For_InvalidMetadataType()
|
||||||
|
{
|
||||||
|
var testMetadata = new DataSourceObjectMetadata
|
||||||
|
{
|
||||||
|
MetadataType = DataSourceMetadataType.Database
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.Throws<ArgumentException>(() => MetadataFactory.CreateDatabaseMetadata(testMetadata, "FakeDatabaseName"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CreateFolderMetadata_ThrowsNullException_For_NullMetadata()
|
||||||
|
{
|
||||||
|
Assert.Throws<InvalidOperationException>(() => MetadataFactory.CreateFolderMetadata(null, "", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CreateClusterMetadata_Returns_DataSourceObjectMetadata()
|
||||||
|
{
|
||||||
|
string clusterName = "FakeClusterName";
|
||||||
|
|
||||||
|
var objectMetadata = MetadataFactory.CreateClusterMetadata(clusterName);
|
||||||
|
|
||||||
|
Assert.AreEqual(DataSourceMetadataType.Cluster, objectMetadata.MetadataType);
|
||||||
|
Assert.AreEqual(DataSourceMetadataType.Cluster.ToString(), objectMetadata.MetadataTypeName);
|
||||||
|
Assert.AreEqual(clusterName, objectMetadata.Name);
|
||||||
|
Assert.AreEqual(clusterName, objectMetadata.PrettyName);
|
||||||
|
Assert.AreEqual(clusterName, objectMetadata.Urn);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CreateDatabaseMetadata_Returns_DataSourceObjectMetadata()
|
||||||
|
{
|
||||||
|
string databaseName = "FakeDatabaseName";
|
||||||
|
var clusterMetadata = new DataSourceObjectMetadata
|
||||||
|
{
|
||||||
|
MetadataType = DataSourceMetadataType.Cluster,
|
||||||
|
Name = "FakeClusterName",
|
||||||
|
Urn = "FakeClusterName"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var objectMetadata = MetadataFactory.CreateDatabaseMetadata(clusterMetadata, databaseName);
|
||||||
|
|
||||||
|
Assert.AreEqual(DataSourceMetadataType.Database, objectMetadata.MetadataType);
|
||||||
|
Assert.AreEqual(DataSourceMetadataType.Database.ToString(), objectMetadata.MetadataTypeName);
|
||||||
|
Assert.AreEqual(databaseName, objectMetadata.Name);
|
||||||
|
Assert.AreEqual(databaseName, objectMetadata.PrettyName);
|
||||||
|
Assert.AreEqual($"{clusterMetadata.Urn}.{databaseName}", objectMetadata.Urn);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CreateFolderMetadata_Returns_FolderMetadata()
|
||||||
|
{
|
||||||
|
string path = "FakeCluster.FakeDatabase.FakeFolder";
|
||||||
|
string name = "FakeFolderName";
|
||||||
|
var parentMetadata = new DataSourceObjectMetadata();
|
||||||
|
|
||||||
|
var objectMetadata = MetadataFactory.CreateFolderMetadata(parentMetadata, path, name);
|
||||||
|
|
||||||
|
Assert.AreEqual(DataSourceMetadataType.Folder, objectMetadata.MetadataType);
|
||||||
|
Assert.AreEqual(DataSourceMetadataType.Folder.ToString(), objectMetadata.MetadataTypeName);
|
||||||
|
Assert.AreEqual(name, objectMetadata.Name);
|
||||||
|
Assert.AreEqual(name, objectMetadata.PrettyName);
|
||||||
|
Assert.AreEqual($"{path}.{name}", objectMetadata.Urn);
|
||||||
|
Assert.AreEqual(parentMetadata, objectMetadata.ParentMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ConvertToDatabaseInfo_Returns_EmptyList_For_NonDatabaseMetadata()
|
||||||
|
{
|
||||||
|
var inputList = new List<DataSourceObjectMetadata>
|
||||||
|
{
|
||||||
|
new DataSourceObjectMetadata
|
||||||
|
{
|
||||||
|
Name = "FakeClusterName"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var databaseInfos = MetadataFactory.ConvertToDatabaseInfo(inputList);
|
||||||
|
|
||||||
|
Assert.AreEqual(0, databaseInfos.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ConvertToDatabaseInfo_Returns_DatabaseInfoList()
|
||||||
|
{
|
||||||
|
var databaseMetadata = new DatabaseMetadata
|
||||||
|
{
|
||||||
|
Name = "FakeDatabaseName",
|
||||||
|
SizeInMB = "2097152" // stored in bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
var inputList = new List<DatabaseMetadata>
|
||||||
|
{
|
||||||
|
databaseMetadata
|
||||||
|
};
|
||||||
|
|
||||||
|
var databaseInfos = MetadataFactory.ConvertToDatabaseInfo(inputList);
|
||||||
|
|
||||||
|
Assert.AreEqual(1, databaseInfos.Count);
|
||||||
|
|
||||||
|
var databaseInfo = databaseInfos.Single();
|
||||||
|
Assert.AreEqual(databaseMetadata.Name, databaseInfo.Options["name"]);
|
||||||
|
Assert.AreEqual("2", databaseInfo.Options["sizeInMB"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ConvertToObjectMetadata_Returns_ListObjectMetadata()
|
||||||
|
{
|
||||||
|
var databaseMetadata = new DataSourceObjectMetadata
|
||||||
|
{
|
||||||
|
PrettyName = "FakeDatabaseName",
|
||||||
|
MetadataTypeName = "Table"
|
||||||
|
};
|
||||||
|
|
||||||
|
var inputList = new List<DataSourceObjectMetadata>
|
||||||
|
{
|
||||||
|
databaseMetadata
|
||||||
|
};
|
||||||
|
|
||||||
|
var objectMetadatas = MetadataFactory.ConvertToObjectMetadata(inputList);
|
||||||
|
|
||||||
|
Assert.AreEqual(1, objectMetadatas.Count);
|
||||||
|
var objectMetadata = objectMetadatas.Single();
|
||||||
|
|
||||||
|
Assert.AreEqual(databaseMetadata.PrettyName, objectMetadata.Name);
|
||||||
|
Assert.AreEqual(databaseMetadata.MetadataTypeName, objectMetadata.MetadataTypeName);
|
||||||
|
Assert.AreEqual(MetadataType.Table, objectMetadata.MetadataType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.LanguageServices;
|
||||||
|
using Microsoft.Kusto.ServiceLayer.LanguageServices.Contracts;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace Microsoft.Kusto.ServiceLayer.UnitTests.LanguageServices
|
||||||
|
{
|
||||||
|
public class AutoCompleteHelperTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void CreateCompletionItem_Returns_CompletionItem()
|
||||||
|
{
|
||||||
|
string label = "";
|
||||||
|
string detail = "";
|
||||||
|
string insertText = "";
|
||||||
|
var itemKind = CompletionItemKind.Method;
|
||||||
|
int row = 1;
|
||||||
|
int startColumn = 2;
|
||||||
|
int endColumn = 3;
|
||||||
|
|
||||||
|
var completionItem = AutoCompleteHelper.CreateCompletionItem(label, detail, insertText, itemKind, row, startColumn, endColumn);
|
||||||
|
|
||||||
|
Assert.IsNotNull(completionItem);
|
||||||
|
Assert.AreEqual(label, completionItem.Label);
|
||||||
|
Assert.AreEqual(itemKind, completionItem.Kind);
|
||||||
|
Assert.AreEqual(detail, completionItem.Detail);
|
||||||
|
Assert.AreEqual(insertText, completionItem.InsertText);
|
||||||
|
|
||||||
|
Assert.IsNotNull(completionItem.TextEdit);
|
||||||
|
Assert.AreEqual(insertText, completionItem.TextEdit.NewText);
|
||||||
|
|
||||||
|
Assert.IsNotNull(completionItem.TextEdit.Range);
|
||||||
|
|
||||||
|
Assert.IsNotNull(completionItem.TextEdit.Range.Start);
|
||||||
|
Assert.AreEqual(row, completionItem.TextEdit.Range.Start.Line);
|
||||||
|
Assert.AreEqual(startColumn, completionItem.TextEdit.Range.Start.Character);
|
||||||
|
|
||||||
|
Assert.IsNotNull(completionItem.TextEdit.Range.End);
|
||||||
|
Assert.AreEqual(row, completionItem.TextEdit.Range.End.Line);
|
||||||
|
Assert.AreEqual(endColumn, completionItem.TextEdit.Range.End.Character);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ConvertQuickInfoToHover_Returns_Null_For_Null_QuickInfoText()
|
||||||
|
{
|
||||||
|
var hover = AutoCompleteHelper.ConvertQuickInfoToHover(null, "", 0, 0, 0);
|
||||||
|
Assert.IsNull(hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ConvertQuickInfoToHover_Returns_Hover()
|
||||||
|
{
|
||||||
|
string quickInfoText = "";
|
||||||
|
string language = "";
|
||||||
|
int row = 0;
|
||||||
|
int startColumn = 0;
|
||||||
|
int endColumn = 0;
|
||||||
|
|
||||||
|
var hover = AutoCompleteHelper.ConvertQuickInfoToHover(quickInfoText, language, row, startColumn, endColumn);
|
||||||
|
|
||||||
|
Assert.IsNotNull(hover);
|
||||||
|
|
||||||
|
Assert.AreEqual(1, hover.Contents.Length);
|
||||||
|
var content = hover.Contents.First();
|
||||||
|
Assert.AreEqual(language, content.Language);
|
||||||
|
Assert.AreEqual(quickInfoText, content.Value);
|
||||||
|
|
||||||
|
Assert.IsNotNull(hover.Range);
|
||||||
|
Assert.IsNotNull(hover.Range.Value.Start);
|
||||||
|
Assert.AreEqual(row, hover.Range.Value.Start.Line);
|
||||||
|
Assert.AreEqual(startColumn, hover.Range.Value.Start.Character);
|
||||||
|
|
||||||
|
Assert.IsNotNull(hover.Range.Value.End);
|
||||||
|
Assert.AreEqual(row, hover.Range.Value.End.Line);
|
||||||
|
Assert.AreEqual(endColumn, hover.Range.Value.End.Character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Moq" />
|
||||||
|
<PackageReference Include="nunit" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.Kusto.ServiceLayer\Microsoft.Kusto.ServiceLayer.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Reference in New Issue
Block a user