diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/AssessmentRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/AssessmentRequest.cs
index c360d854..ed48a0d0 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/AssessmentRequest.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/AssessmentRequest.cs
@@ -1,129 +1,129 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System.Collections.Generic;
-
-using Microsoft.SqlServer.Management.Assessment;
-
-namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts
-{
- ///
- /// Parameters for executing a query from a provided string
- ///
- public class AssessmentParams
- {
- ///
- /// Gets or sets the owner uri to get connection from
- ///
- public string OwnerUri { get; set; }
-
- ///
- /// Gets or sets the target type
- ///
- public SqlObjectType TargetType { get; set; }
- }
-
- ///
- /// Describes an item returned by SQL Assessment RPC methods
- ///
- public class AssessmentItemInfo
- {
- ///
- /// Gets or sets assessment ruleset version.
- ///
- public string RulesetVersion { get; set; }
-
- ///
- /// Gets or sets assessment ruleset name
- ///
- public string RulesetName { get; set; }
-
- ///
- /// Gets or sets assessed target's type.
- /// Supported values: 1 - server, 2 - database.
- ///
- public SqlObjectType TargetType { get; set; }
-
- ///
- /// Gets or sets the assessed object's name.
- ///
- public string TargetName { get; set; }
-
- ///
- /// Gets or sets check's ID.
- ///
- public string CheckId { get; set; }
-
- ///
- /// Gets or sets tags assigned to this item.
- ///
- public string[] Tags { get; set; }
-
- ///
- /// Gets or sets a display name for this item.
- ///
- public string DisplayName { get; set; }
-
- ///
- /// Gets or sets a brief description of the item's purpose.
- ///
- public string Description { get; set; }
-
- ///
- /// Gets or sets a containing
- /// an link to a page providing detailed explanation
- /// of the best practice.
- ///
- public string HelpLink { get; set; }
-
- ///
- /// Gets or sets a indicating
- /// severity level assigned to this items.
- /// Values are: "Information", "Warning", "Critical".
- ///
- public string Level { get; set; }
- }
-
- ///
- /// Generic SQL Assessment Result
- ///
- ///
- /// Result item's type derived from
- ///
- public class AssessmentResultData
- where T : AssessmentItemInfo
- {
- ///
- /// Gets the collection of assessment results.
- ///
- public List Items { get; } = new List();
-
- ///
- /// Gets or sets SQL Assessment API version.
- ///
- public string ApiVersion { get; set; }
- }
-
- ///
- /// Generic SQL Assessment Result
- ///
- ///
- /// Result item's type derived from
- ///
- public class AssessmentResult : AssessmentResultData
- where T : AssessmentItemInfo
- {
- ///
- /// Gets or sets a value indicating
- /// if assessment operation was successful.
- ///
- public bool Success { get; set; }
-
- ///
- /// Gets or sets an status message for the operation.
- ///
- public string ErrorMessage { get; set; }
- }
-}
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Collections.Generic;
+
+using Microsoft.SqlServer.Management.Assessment;
+
+namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts
+{
+ ///
+ /// Parameters for executing a query from a provided string
+ ///
+ public class AssessmentParams
+ {
+ ///
+ /// Gets or sets the owner uri to get connection from
+ ///
+ public string OwnerUri { get; set; }
+
+ ///
+ /// Gets or sets the target type
+ ///
+ public SqlObjectType TargetType { get; set; }
+ }
+
+ ///
+ /// Describes an item returned by SQL Assessment RPC methods
+ ///
+ public class AssessmentItemInfo
+ {
+ ///
+ /// Gets or sets assessment ruleset version.
+ ///
+ public string RulesetVersion { get; set; }
+
+ ///
+ /// Gets or sets assessment ruleset name
+ ///
+ public string RulesetName { get; set; }
+
+ ///
+ /// Gets or sets assessed target's type.
+ /// Supported values: 1 - server, 2 - database.
+ ///
+ public SqlObjectType TargetType { get; set; }
+
+ ///
+ /// Gets or sets the assessed object's name.
+ ///
+ public string TargetName { get; set; }
+
+ ///
+ /// Gets or sets check's ID.
+ ///
+ public string CheckId { get; set; }
+
+ ///
+ /// Gets or sets tags assigned to this item.
+ ///
+ public string[] Tags { get; set; }
+
+ ///
+ /// Gets or sets a display name for this item.
+ ///
+ public string DisplayName { get; set; }
+
+ ///
+ /// Gets or sets a brief description of the item's purpose.
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Gets or sets a containing
+ /// an link to a page providing detailed explanation
+ /// of the best practice.
+ ///
+ public string HelpLink { get; set; }
+
+ ///
+ /// Gets or sets a indicating
+ /// severity level assigned to this items.
+ /// Values are: "Information", "Warning", "Critical".
+ ///
+ public string Level { get; set; }
+ }
+
+ ///
+ /// Generic SQL Assessment Result
+ ///
+ ///
+ /// Result item's type derived from
+ ///
+ public class AssessmentResultData
+ where T : AssessmentItemInfo
+ {
+ ///
+ /// Gets the collection of assessment results.
+ ///
+ public List Items { get; } = new List();
+
+ ///
+ /// Gets or sets SQL Assessment API version.
+ ///
+ public string ApiVersion { get; set; }
+ }
+
+ ///
+ /// Generic SQL Assessment Result
+ ///
+ ///
+ /// Result item's type derived from
+ ///
+ public class AssessmentResult : AssessmentResultData
+ where T : AssessmentItemInfo
+ {
+ ///
+ /// Gets or sets a value indicating
+ /// if assessment operation was successful.
+ ///
+ public bool Success { get; set; }
+
+ ///
+ /// Gets or sets an status message for the operation.
+ ///
+ public string ErrorMessage { get; set; }
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/GenerateScriptRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/GenerateScriptRequest.cs
index ead2b543..0a9f666d 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/GenerateScriptRequest.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/GenerateScriptRequest.cs
@@ -1,56 +1,56 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System.Collections.Generic;
-using Microsoft.SqlTools.Hosting.Protocol.Contracts;
-using Microsoft.SqlTools.ServiceLayer.TaskServices;
-using Microsoft.SqlTools.ServiceLayer.Utility;
-
-namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts
-{
- ///
- /// Parameters for executing a query from a provided string
- ///
- public class GenerateScriptParams
- {
- ///
- /// Gets or sets a list of assessment result items
- /// to be written to a table
- ///
- public List Items { get; set; }
-
- public TaskExecutionMode TaskExecutionMode { get; set; }
-
- public string TargetServerName { get; set; }
-
- public string TargetDatabaseName { get; set; }
- }
-
- public class GenerateScriptResult
- {
- ///
- /// Gets or sets a value indicating
- /// if assessment operation was successful
- ///
- public bool Success { get; set; }
-
- ///
- /// Gets or sets an status message for the operation
- ///
- public string ErrorMessage { get; set; }
-
- ///
- /// Gets or sets script text
- ///
- public string Script { get; set; }
- }
-
- public class GenerateScriptRequest
- {
- public static readonly
- RequestType Type =
- RequestType.Create("assessment/generateScript");
- }
-}
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Collections.Generic;
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+using Microsoft.SqlTools.ServiceLayer.TaskServices;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+
+namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts
+{
+ ///
+ /// Parameters for executing a query from a provided string
+ ///
+ public class GenerateScriptParams
+ {
+ ///
+ /// Gets or sets a list of assessment result items
+ /// to be written to a table
+ ///
+ public List Items { get; set; }
+
+ public TaskExecutionMode TaskExecutionMode { get; set; }
+
+ public string TargetServerName { get; set; }
+
+ public string TargetDatabaseName { get; set; }
+ }
+
+ public class GenerateScriptResult
+ {
+ ///
+ /// Gets or sets a value indicating
+ /// if assessment operation was successful
+ ///
+ public bool Success { get; set; }
+
+ ///
+ /// Gets or sets an status message for the operation
+ ///
+ public string ErrorMessage { get; set; }
+
+ ///
+ /// Gets or sets script text
+ ///
+ public string Script { get; set; }
+ }
+
+ public class GenerateScriptRequest
+ {
+ public static readonly
+ RequestType Type =
+ RequestType.Create("assessment/generateScript");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/GetAssessmentItemsRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/GetAssessmentItemsRequest.cs
index b194da7e..c194b7a5 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/GetAssessmentItemsRequest.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/GetAssessmentItemsRequest.cs
@@ -1,33 +1,33 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.SqlTools.Hosting.Protocol.Contracts;
-
-namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts
-{
- ///
- /// Parameters for executing a query from a provided string
- ///
- public class GetAssessmentItemsParams : AssessmentParams
- {
- // a placeholder for future specialization
- }
-
- ///
- /// Describes a check used to assess SQL Server objects.
- ///
- public class CheckInfo : AssessmentItemInfo
- {
- // a placeholder for future specialization
- }
-
-
- public class GetAssessmentItemsRequest
- {
- public static readonly RequestType> Type =
- RequestType>.Create(
- "assessment/getAssessmentItems");
- }
-}
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+
+namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts
+{
+ ///
+ /// Parameters for executing a query from a provided string
+ ///
+ public class GetAssessmentItemsParams : AssessmentParams
+ {
+ // a placeholder for future specialization
+ }
+
+ ///
+ /// Describes a check used to assess SQL Server objects.
+ ///
+ public class CheckInfo : AssessmentItemInfo
+ {
+ // a placeholder for future specialization
+ }
+
+
+ public class GetAssessmentItemsRequest
+ {
+ public static readonly RequestType> Type =
+ RequestType>.Create(
+ "assessment/getAssessmentItems");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/InvokeRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/InvokeRequest.cs
index 6df4a01d..ede6a0ae 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/InvokeRequest.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/Contracts/InvokeRequest.cs
@@ -1,82 +1,82 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using Microsoft.SqlTools.Hosting.Protocol.Contracts;
-using Microsoft.SqlTools.ServiceLayer.Utility;
-
-namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts
-{
- ///
- /// Parameters for executing a query from a provided string
- ///
- public class InvokeParams : AssessmentParams
- {
- // a placeholder for future specialization
- }
-
- ///
- /// SQL Assessment result item kind.
- ///
- ///
- /// SQL Assessment run is a set of checks. Every check
- /// may return a result item. Normally it is a note containing
- /// recommendations on improving target's configuration.
- /// But some checks may fail to obtain data due to access
- /// restrictions or data integrity. In this case
- /// the check produces an error or a warning.
- ///
- public enum AssessmentResultItemKind
- {
- ///
- /// SQL Assessment item contains recommendation
- ///
- Note = 0,
-
- ///
- /// SQL Assessment item contains a warning on
- /// limited assessment capabilities
- ///
- Warning = 1,
-
- ///
- /// SQL Assessment item contain a description of
- /// error occured in the course of assessment run
- ///
- Error = 2
- }
-
- ///
- /// Describes an assessment result item
- /// containing a recommendation based on best practices.
- ///
- public class AssessmentResultItem : AssessmentItemInfo
- {
- ///
- /// Gets or sets a message to the user
- /// containing the recommendation.
- ///
- public string Message { get; set; }
-
- ///
- /// Gets or sets result type:
- /// 0 - real result, 1 - warning, 2 - error.
- ///
- public AssessmentResultItemKind Kind { get; set; }
-
- ///
- /// Gets or sets date and time
- /// when the item had been acquired.
- ///
- public DateTimeOffset Timestamp { get; set; }
- }
-
- public class InvokeRequest
- {
- public static readonly
- RequestType> Type =
- RequestType>.Create("assessment/invoke");
- }
-}
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+
+namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts
+{
+ ///
+ /// Parameters for executing a query from a provided string
+ ///
+ public class InvokeParams : AssessmentParams
+ {
+ // a placeholder for future specialization
+ }
+
+ ///
+ /// SQL Assessment result item kind.
+ ///
+ ///
+ /// SQL Assessment run is a set of checks. Every check
+ /// may return a result item. Normally it is a note containing
+ /// recommendations on improving target's configuration.
+ /// But some checks may fail to obtain data due to access
+ /// restrictions or data integrity. In this case
+ /// the check produces an error or a warning.
+ ///
+ public enum AssessmentResultItemKind
+ {
+ ///
+ /// SQL Assessment item contains recommendation
+ ///
+ Note = 0,
+
+ ///
+ /// SQL Assessment item contains a warning on
+ /// limited assessment capabilities
+ ///
+ Warning = 1,
+
+ ///
+ /// SQL Assessment item contain a description of
+ /// error occured in the course of assessment run
+ ///
+ Error = 2
+ }
+
+ ///
+ /// Describes an assessment result item
+ /// containing a recommendation based on best practices.
+ ///
+ public class AssessmentResultItem : AssessmentItemInfo
+ {
+ ///
+ /// Gets or sets a message to the user
+ /// containing the recommendation.
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Gets or sets result type:
+ /// 0 - real result, 1 - warning, 2 - error.
+ ///
+ public AssessmentResultItemKind Kind { get; set; }
+
+ ///
+ /// Gets or sets date and time
+ /// when the item had been acquired.
+ ///
+ public DateTimeOffset Timestamp { get; set; }
+ }
+
+ public class InvokeRequest
+ {
+ public static readonly
+ RequestType> Type =
+ RequestType>.Create("assessment/invoke");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/GenerateScriptOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/GenerateScriptOperation.cs
index 65a1a0b3..4f306a1f 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/GenerateScriptOperation.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/GenerateScriptOperation.cs
@@ -27,8 +27,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment
///
/// Gets the unique id associated with this instance.
///
- public string OperationId { get; set; }
-
+ public string OperationId { get; set; }
+
///
/// Gets the parameters containing assessment results
/// to be stored in a data table.
@@ -44,8 +44,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment
///
/// Gets or sets the sql task that's executing the operation
///
- public SqlTask SqlTask { get; set; }
-
+ public SqlTask SqlTask { get; set; }
+
public GenerateScriptOperation(GenerateScriptParams parameters)
{
Validate.IsNotNull(nameof(parameters), parameters);
@@ -92,24 +92,29 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment
CancellationToken cancellationToken)
{
const string scriptPrologue =
- @"IF (NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'AssessmentResult'))
-BEGIN
- CREATE TABLE [dbo].[AssessmentResult](
- [CheckName] [nvarchar](max) NOT NULL,
- [CheckId] [nvarchar](max) NOT NULL,
- [RulesetName] [nvarchar](max) NOT NULL,
- [RulesetVersion] [nvarchar](max) NOT NULL,
- [Severity] [nvarchar](max) NOT NULL,
- [Message] [nvarchar](max) NOT NULL,
- [TargetPath] [nvarchar](max) NOT NULL,
- [TargetType] [nvarchar](max) NOT NULL,
- [HelpLink] [nvarchar](max) NOT NULL,
- [Timestamp] [datetimeoffset](7) NOT NULL
- )
-END
-GO
-INSERT INTO [dbo].[AssessmentResult] ([CheckName],[CheckId],[RulesetName],[RulesetVersion],[Severity],[Message],[TargetPath],[TargetType],[HelpLink],[Timestamp])
-VALUES";
+ @"IF (NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'AssessmentResult'))
+BEGIN
+ CREATE TABLE [dbo].[AssessmentResult](
+ [CheckName] [nvarchar](max),
+ [CheckId] [nvarchar](max),
+ [RulesetName] [nvarchar](max),
+ [RulesetVersion] [nvarchar](max),
+ [Severity] [nvarchar](max),
+ [Message] [nvarchar](max),
+ [TargetPath] [nvarchar](max),
+ [TargetType] [nvarchar](max),
+ [HelpLink] [nvarchar](max),
+ [Timestamp] [datetimeoffset](7)
+ )
+END
+GO
+INSERT INTO [dbo].[AssessmentResult] ([CheckName],[CheckId],[RulesetName],[RulesetVersion],[Severity],[Message],[TargetPath],[TargetType],[HelpLink],[Timestamp])
+ SELECT rpt.[CheckName],rpt.[CheckId],rpt.[RulesetName],rpt.[RulesetVersion],rpt.[Severity],rpt.[Message],rpt.[TargetPath],rpt.[TargetType],rpt.[HelpLink],rpt.[Timestamp]
+ FROM (VALUES ";
+
+ const string scriptEpilogue =
+ @"
+ ) rpt([CheckName],[CheckId],[RulesetName],[RulesetVersion],[Severity],[Message],[TargetPath],[TargetType],[HelpLink],[Timestamp])";
var sb = new StringBuilder();
if (generateScriptParams.Items != null)
@@ -122,11 +127,14 @@ VALUES";
if (item.Kind == AssessmentResultItemKind.Note)
{
sb.Append(
- $"\r\n('{CUtils.EscapeStringSQuote(item.DisplayName)}','{CUtils.EscapeStringSQuote(item.CheckId)}','{CUtils.EscapeStringSQuote(item.RulesetName)}','{item.RulesetVersion}','{item.Level}','{CUtils.EscapeStringSQuote(item.Message)}','{CUtils.EscapeStringSQuote(item.TargetName)}','{item.TargetType}','{CUtils.EscapeStringSQuote(item.HelpLink)}','{item.Timestamp:yyyy-MM-dd hh:mm:ss.fff zzz}'),");
+ $@"
+ ('{CUtils.EscapeStringSQuote(item.DisplayName)}','{CUtils.EscapeStringSQuote(item.CheckId)}','{CUtils.EscapeStringSQuote(item.RulesetName)}','{item.RulesetVersion}','{item.Level}','{CUtils.EscapeStringSQuote(item.Message)}','{CUtils.EscapeStringSQuote(item.TargetName)}','{item.TargetType}','{CUtils.EscapeStringSQuote(item.HelpLink)}','{item.Timestamp:yyyy-MM-dd hh:mm:ss.fff zzz}'),");
}
}
sb.Length -= 1;
+
+ sb.Append(scriptEpilogue);
}
return sb.ToString();
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/SqlAssessmentService.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/SqlAssessmentService.cs
index 85ca7984..d4a028b4 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/SqlAssessmentService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlAssessment/SqlAssessmentService.cs
@@ -1,507 +1,507 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading.Tasks;
-
-using Microsoft.SqlServer.Management.Assessment;
-using Microsoft.SqlServer.Management.Assessment.Configuration;
-using Microsoft.SqlTools.Hosting.Protocol;
-using Microsoft.SqlTools.ServiceLayer.Connection;
-using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
-using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
-using Microsoft.SqlTools.ServiceLayer.Hosting;
-using Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts;
-using Microsoft.SqlTools.ServiceLayer.SqlContext;
-using Microsoft.SqlTools.ServiceLayer.TaskServices;
-using Microsoft.SqlTools.ServiceLayer.Utility;
-using Microsoft.SqlTools.ServiceLayer.Workspace;
-using Microsoft.SqlTools.Utility;
-
-using AssessmentResultItem = Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts.AssessmentResultItem;
-using ConnectionType = Microsoft.SqlTools.ServiceLayer.Connection.ConnectionType;
-using InvokeParams = Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts.InvokeParams;
-using InvokeRequest = Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts.InvokeRequest;
-
-namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment
-{
- ///
- /// Service for running SQL Assessment.
- ///
- public sealed class SqlAssessmentService : IDisposable
- {
- private const string ApiVersion = "1.0";
-
- #region Singleton Instance Implementation
-
- private static readonly Lazy LazyInstance
- = new Lazy(() => new SqlAssessmentService());
-
- internal SqlAssessmentService(
- ConnectionService connService,
- WorkspaceService workspaceService)
- {
- ConnectionService = connService;
- WorkspaceService = workspaceService;
- }
-
- private SqlAssessmentService()
- {
- ConnectionService = ConnectionService.Instance;
- WorkspaceService = WorkspaceService.Instance;
- }
-
- ///
- /// Singleton instance of the query execution service
- ///
- public static SqlAssessmentService Instance => LazyInstance.Value;
-
- #endregion
-
- #region Properties
-
- ///
- /// Gets the used to run assessment operations.
- ///
- internal Engine Engine { get; } = new Engine();
-
- ///
- /// Gets the instance of the connection service,
- /// used to get the connection info for a given owner URI.
- ///
- private ConnectionService ConnectionService { get; }
-
- private WorkspaceService WorkspaceService { get; }
-
- ///
- /// Holds a map from the
- /// to a that is being ran.
- ///
- private readonly Lazy> activeRequests =
- new Lazy>(() => new ConcurrentDictionary());
-
- ///
- /// Gets a map from the
- /// to a that is being ran.
- ///
- internal ConcurrentDictionary ActiveRequests => activeRequests.Value;
-
- #endregion
-
- ///
- /// Initializes the service with the service host,
- /// registers request handlers and shutdown event handler.
- ///
- /// The service host instance to register with
- public void InitializeService(ServiceHost serviceHost)
- {
- // Register handlers for requests
- serviceHost.SetRequestHandler(InvokeRequest.Type, HandleInvokeRequest);
- serviceHost.SetRequestHandler(GetAssessmentItemsRequest.Type, HandleGetAssessmentItemsRequest);
- serviceHost.SetRequestHandler(GenerateScriptRequest.Type, HandleGenerateScriptRequest);
-
- // Register handler for shutdown event
- serviceHost.RegisterShutdownTask((shutdownParams, requestContext) =>
- {
- Dispose();
- return Task.FromResult(0);
- });
- }
-
- #region Request Handlers
-
- internal Task HandleGetAssessmentItemsRequest(
- GetAssessmentItemsParams itemsParams,
- RequestContext> requestContext)
- {
- return this.HandleAssessmentRequest(requestContext, itemsParams, this.GetAssessmentItems);
- }
-
- internal Task HandleInvokeRequest(
- InvokeParams invokeParams,
- RequestContext> requestContext)
- {
- return this.HandleAssessmentRequest(requestContext, invokeParams, this.InvokeSqlAssessment);
- }
-
- internal async Task HandleGenerateScriptRequest(
- GenerateScriptParams parameters,
- RequestContext requestContext)
- {
- GenerateScriptOperation operation = null;
- try
- {
- operation = new GenerateScriptOperation(parameters);
- TaskMetadata metadata = new TaskMetadata
- {
- TaskOperation = operation,
- TaskExecutionMode = parameters.TaskExecutionMode,
- ServerName = parameters.TargetServerName,
- DatabaseName = parameters.TargetDatabaseName,
- Name = SR.SqlAssessmentGenerateScriptTaskName
- };
-
- var _ = SqlTaskManager.Instance.CreateAndRun(metadata);
-
- await requestContext.SendResult(new ResultStatus
- {
- Success = true,
- ErrorMessage = operation.ErrorMessage
- });
- }
- catch (Exception e)
- {
- Logger.Write(TraceEventType.Error, "SQL Assessment: failed to generate a script. Error: " + e);
- await requestContext.SendResult(new ResultStatus()
- {
- Success = false,
- ErrorMessage = operation == null ? e.Message : operation.ErrorMessage,
- });
- }
- }
-
- #endregion
-
- #region Helpers
-
- private async Task HandleAssessmentRequest(
- RequestContext> requestContext,
- AssessmentParams requestParams,
- Func>> assessmentFunction)
- where TResult : AssessmentItemInfo
- {
- try
- {
- string randomUri = Guid.NewGuid().ToString();
-
- // get connection
- if (!ConnectionService.TryFindConnection(requestParams.OwnerUri, out var connInfo))
- {
- await requestContext.SendError(SR.SqlAssessmentQueryInvalidOwnerUri);
- return;
- }
-
- ConnectParams connectParams = new ConnectParams
- {
- OwnerUri = randomUri,
- Connection = connInfo.ConnectionDetails,
- Type = ConnectionType.Default
- };
-
- if(!connInfo.TryGetConnection(ConnectionType.Default, out var connection))
- {
- await requestContext.SendError(SR.SqlAssessmentConnectingError);
- }
-
- var workTask = CallAssessmentEngine(
- requestParams,
- connectParams,
- randomUri,
- assessmentFunction)
- .ContinueWith(async tsk =>
- {
- await requestContext.SendResult(tsk.Result);
- });
-
- ActiveRequests.TryAdd(randomUri, workTask);
- }
- catch (Exception ex)
- {
- if (ex is StackOverflowException || ex is OutOfMemoryException)
- {
- throw;
- }
-
- await requestContext.SendError(ex.ToString());
- }
- }
-
- ///
- /// This function obtains a live connection, then calls
- /// an assessment operation specified by
- ///
- ///
- /// SQL Assessment result item type.
- ///
- ///
- /// Request parameters passed from the host.
- ///
- ///
- /// Connection parameters used to identify and access the target.
- ///
- ///
- /// An URI identifying the request task to enable concurrent execution.
- ///
- ///
- /// A function performing assessment operation for given target.
- ///
- ///
- /// Returns for given target.
- ///
- internal async Task> CallAssessmentEngine(
- AssessmentParams requestParams,
- ConnectParams connectParams,
- string taskUri,
- Func>> assessmentFunc)
- where TResult : AssessmentItemInfo
-
- {
- var result = new AssessmentResult
- {
- ApiVersion = ApiVersion
- };
-
- await ConnectionService.Connect(connectParams);
-
- var connection = await ConnectionService.Instance.GetOrOpenConnection(taskUri, ConnectionType.Query);
-
- try
- {
- var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
- var hostInfo = ReliableConnectionHelper.GetServerHostInfo(connection);
-
- var server = new SqlObjectLocator
- {
- Connection = connection,
- EngineEdition = GetEngineEdition(serverInfo.EngineEditionId),
- Name = serverInfo.ServerName,
- ServerName = serverInfo.ServerName,
- Type = SqlObjectType.Server,
- Urn = serverInfo.ServerName,
- Version = Version.Parse(serverInfo.ServerVersion),
- Platform = hostInfo.Platform
- };
-
- switch (requestParams.TargetType)
- {
- case SqlObjectType.Server:
- Logger.Write(
- TraceEventType.Verbose,
- $"SQL Assessment: running an operation on a server, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
-
- result.Items.AddRange(await assessmentFunc(server));
-
- Logger.Write(
- TraceEventType.Verbose,
- $"SQL Assessment: finished an operation on a server, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
- break;
- case SqlObjectType.Database:
- var db = GetDatabaseLocator(server, connection.Database);
- Logger.Write(
- TraceEventType.Verbose,
- $"SQL Assessment: running an operation on a database, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
-
- result.Items.AddRange(await assessmentFunc(db));
-
- Logger.Write(
- TraceEventType.Verbose,
- $"SQL Assessment: finished an operation on a database, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
- break;
- }
-
- result.Success = true;
- }
- finally
- {
- ActiveRequests.TryRemove(taskUri, out _);
- ConnectionService.Disconnect(new DisconnectParams { OwnerUri = taskUri, Type = null });
- }
-
- return result;
- }
-
- ///
- /// Invokes SQL Assessment and formats results.
- ///
- ///
- /// A sequence of target servers or databases to be assessed.
- ///
- ///
- /// Returns a
- /// containing assessment results.
- ///
- ///
- /// Internal for testing
- ///
- internal async Task> InvokeSqlAssessment(SqlObjectLocator target)
- {
- var resultsList = await Engine.GetAssessmentResultsList(target);
- Logger.Write(TraceEventType.Verbose, $"SQL Assessment: got {resultsList.Count} results.");
-
- return resultsList.Select(TranslateAssessmentResult).ToList();
- }
-
- ///
- /// Gets the list of checks for given target servers or databases.
- ///
- ///
- /// A sequence of target servers or databases.
- ///
- ///
- /// Returns an
- /// containing checks available for given .
- ///
- internal Task> GetAssessmentItems(SqlObjectLocator target)
- {
- var result = new List();
-
- var resultsList = Engine.GetChecks(target).ToList();
- Logger.Write(TraceEventType.Verbose, $"SQL Assessment: got {resultsList.Count} items.");
-
- foreach (var r in resultsList)
- {
- var targetName = target.Type != SqlObjectType.Server
- ? $"{target.ServerName}:{target.Name}"
- : target.Name;
-
- var item = new CheckInfo()
- {
- CheckId = r.Id,
- Description = r.Description,
- DisplayName = r.DisplayName,
- HelpLink = r.HelpLink,
- Level = r.Level.ToString(),
- TargetName = targetName,
- Tags = r.Tags.ToArray(),
- TargetType = target.Type,
- RulesetName = Engine.Configuration.DefaultRuleset.Name,
- RulesetVersion = Engine.Configuration.DefaultRuleset.Version.ToString()
- };
-
- result.Add(item);
- }
-
- return Task.FromResult(result);
- }
-
- private AssessmentResultItem TranslateAssessmentResult(IAssessmentResult r)
- {
- var item = new AssessmentResultItem
- {
- CheckId = r.Check.Id,
- Description = r.Check.Description,
- DisplayName = r.Check.DisplayName,
- HelpLink = r.Check.HelpLink,
- Level = r.Check.Level.ToString(),
- Message = r.Message,
- TargetName = r.TargetPath,
- Tags = r.Check.Tags.ToArray(),
- TargetType = r.TargetType,
- RulesetVersion = Engine.Configuration.DefaultRuleset.Version.ToString(),
- RulesetName = Engine.Configuration.DefaultRuleset.Name,
- Timestamp = r.Timestamp
- };
-
- if (r is IAssessmentNote)
- {
- item.Kind = AssessmentResultItemKind.Note;
- }
- else if (r is IAssessmentWarning)
- {
- item.Kind = AssessmentResultItemKind.Warning;
- }
- else if (r is IAssessmentError)
- {
- item.Kind = AssessmentResultItemKind.Error;
- }
-
- return item;
- }
-
- ///
- /// Constructs a for specified database.
- ///
- /// Target server locator.
- /// Target database name.
- /// Returns a locator for target database.
- private static SqlObjectLocator GetDatabaseLocator(SqlObjectLocator server, string databaseName)
- {
- return new SqlObjectLocator
- {
- Connection = server.Connection,
- EngineEdition = server.EngineEdition,
- Name = databaseName,
- Platform = server.Platform,
- ServerName = server.Name,
- Type = SqlObjectType.Database,
- Urn = $"{server.Name}:{databaseName}",
- Version = server.Version
- };
- }
-
- ///
- /// Converts numeric of engine edition
- /// returned by SERVERPROPERTY('EngineEdition').
- ///
- ///
- /// A number returned by SERVERPROPERTY('EngineEdition').
- ///
- /// Engine edition is not supported.
- ///
- /// Returns a
- /// corresponding to the .
- ///
- private static SqlEngineEdition GetEngineEdition(int representation)
- {
- switch (representation)
- {
- case 1: return SqlEngineEdition.PersonalOrDesktopEngine;
- case 2: return SqlEngineEdition.Standard;
- case 3: return SqlEngineEdition.Enterprise;
- case 4: return SqlEngineEdition.Express;
- case 5: return SqlEngineEdition.AzureDatabase;
- case 6: return SqlEngineEdition.DataWarehouse;
- case 7: return SqlEngineEdition.StretchDatabase;
- case 8: return SqlEngineEdition.ManagedInstance;
- default:
- throw new ArgumentOutOfRangeException(nameof(representation),
- SR.SqlAssessmentUnsuppoertedEdition(representation));
- }
- }
-
- #endregion
-
- #region IDisposable Implementation
-
- private bool disposed;
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- private void Dispose(bool disposing)
- {
- if (disposed)
- {
- return;
- }
-
- if (disposing)
- {
- foreach (var request in ActiveRequests)
- {
- request.Value.Dispose();
- }
-
- ActiveRequests.Clear();
- }
-
- disposed = true;
- }
-
- ~SqlAssessmentService()
- {
- Dispose(false);
- }
-
- #endregion
- }
-}
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+using Microsoft.SqlServer.Management.Assessment;
+using Microsoft.SqlServer.Management.Assessment.Configuration;
+using Microsoft.SqlTools.Hosting.Protocol;
+using Microsoft.SqlTools.ServiceLayer.Connection;
+using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
+using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
+using Microsoft.SqlTools.ServiceLayer.Hosting;
+using Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts;
+using Microsoft.SqlTools.ServiceLayer.SqlContext;
+using Microsoft.SqlTools.ServiceLayer.TaskServices;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+using Microsoft.SqlTools.ServiceLayer.Workspace;
+using Microsoft.SqlTools.Utility;
+
+using AssessmentResultItem = Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts.AssessmentResultItem;
+using ConnectionType = Microsoft.SqlTools.ServiceLayer.Connection.ConnectionType;
+using InvokeParams = Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts.InvokeParams;
+using InvokeRequest = Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts.InvokeRequest;
+
+namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment
+{
+ ///
+ /// Service for running SQL Assessment.
+ ///
+ public sealed class SqlAssessmentService : IDisposable
+ {
+ private const string ApiVersion = "1.0";
+
+ #region Singleton Instance Implementation
+
+ private static readonly Lazy LazyInstance
+ = new Lazy(() => new SqlAssessmentService());
+
+ internal SqlAssessmentService(
+ ConnectionService connService,
+ WorkspaceService workspaceService)
+ {
+ ConnectionService = connService;
+ WorkspaceService = workspaceService;
+ }
+
+ private SqlAssessmentService()
+ {
+ ConnectionService = ConnectionService.Instance;
+ WorkspaceService = WorkspaceService.Instance;
+ }
+
+ ///
+ /// Singleton instance of the query execution service
+ ///
+ public static SqlAssessmentService Instance => LazyInstance.Value;
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Gets the used to run assessment operations.
+ ///
+ internal Engine Engine { get; } = new Engine();
+
+ ///
+ /// Gets the instance of the connection service,
+ /// used to get the connection info for a given owner URI.
+ ///
+ private ConnectionService ConnectionService { get; }
+
+ private WorkspaceService WorkspaceService { get; }
+
+ ///
+ /// Holds a map from the
+ /// to a that is being ran.
+ ///
+ private readonly Lazy> activeRequests =
+ new Lazy>(() => new ConcurrentDictionary());
+
+ ///
+ /// Gets a map from the
+ /// to a that is being ran.
+ ///
+ internal ConcurrentDictionary ActiveRequests => activeRequests.Value;
+
+ #endregion
+
+ ///
+ /// Initializes the service with the service host,
+ /// registers request handlers and shutdown event handler.
+ ///
+ /// The service host instance to register with
+ public void InitializeService(ServiceHost serviceHost)
+ {
+ // Register handlers for requests
+ serviceHost.SetRequestHandler(InvokeRequest.Type, HandleInvokeRequest);
+ serviceHost.SetRequestHandler(GetAssessmentItemsRequest.Type, HandleGetAssessmentItemsRequest);
+ serviceHost.SetRequestHandler(GenerateScriptRequest.Type, HandleGenerateScriptRequest);
+
+ // Register handler for shutdown event
+ serviceHost.RegisterShutdownTask((shutdownParams, requestContext) =>
+ {
+ Dispose();
+ return Task.FromResult(0);
+ });
+ }
+
+ #region Request Handlers
+
+ internal Task HandleGetAssessmentItemsRequest(
+ GetAssessmentItemsParams itemsParams,
+ RequestContext> requestContext)
+ {
+ return this.HandleAssessmentRequest(requestContext, itemsParams, this.GetAssessmentItems);
+ }
+
+ internal Task HandleInvokeRequest(
+ InvokeParams invokeParams,
+ RequestContext> requestContext)
+ {
+ return this.HandleAssessmentRequest(requestContext, invokeParams, this.InvokeSqlAssessment);
+ }
+
+ internal async Task HandleGenerateScriptRequest(
+ GenerateScriptParams parameters,
+ RequestContext requestContext)
+ {
+ GenerateScriptOperation operation = null;
+ try
+ {
+ operation = new GenerateScriptOperation(parameters);
+ TaskMetadata metadata = new TaskMetadata
+ {
+ TaskOperation = operation,
+ TaskExecutionMode = parameters.TaskExecutionMode,
+ ServerName = parameters.TargetServerName,
+ DatabaseName = parameters.TargetDatabaseName,
+ Name = SR.SqlAssessmentGenerateScriptTaskName
+ };
+
+ var _ = SqlTaskManager.Instance.CreateAndRun(metadata);
+
+ await requestContext.SendResult(new ResultStatus
+ {
+ Success = true,
+ ErrorMessage = operation.ErrorMessage
+ });
+ }
+ catch (Exception e)
+ {
+ Logger.Write(TraceEventType.Error, "SQL Assessment: failed to generate a script. Error: " + e);
+ await requestContext.SendResult(new ResultStatus()
+ {
+ Success = false,
+ ErrorMessage = operation == null ? e.Message : operation.ErrorMessage,
+ });
+ }
+ }
+
+ #endregion
+
+ #region Helpers
+
+ private async Task HandleAssessmentRequest(
+ RequestContext> requestContext,
+ AssessmentParams requestParams,
+ Func>> assessmentFunction)
+ where TResult : AssessmentItemInfo
+ {
+ try
+ {
+ string randomUri = Guid.NewGuid().ToString();
+
+ // get connection
+ if (!ConnectionService.TryFindConnection(requestParams.OwnerUri, out var connInfo))
+ {
+ await requestContext.SendError(SR.SqlAssessmentQueryInvalidOwnerUri);
+ return;
+ }
+
+ ConnectParams connectParams = new ConnectParams
+ {
+ OwnerUri = randomUri,
+ Connection = connInfo.ConnectionDetails,
+ Type = ConnectionType.Default
+ };
+
+ if(!connInfo.TryGetConnection(ConnectionType.Default, out var connection))
+ {
+ await requestContext.SendError(SR.SqlAssessmentConnectingError);
+ }
+
+ var workTask = CallAssessmentEngine(
+ requestParams,
+ connectParams,
+ randomUri,
+ assessmentFunction)
+ .ContinueWith(async tsk =>
+ {
+ await requestContext.SendResult(tsk.Result);
+ });
+
+ ActiveRequests.TryAdd(randomUri, workTask);
+ }
+ catch (Exception ex)
+ {
+ if (ex is StackOverflowException || ex is OutOfMemoryException)
+ {
+ throw;
+ }
+
+ await requestContext.SendError(ex.ToString());
+ }
+ }
+
+ ///
+ /// This function obtains a live connection, then calls
+ /// an assessment operation specified by
+ ///
+ ///
+ /// SQL Assessment result item type.
+ ///
+ ///
+ /// Request parameters passed from the host.
+ ///
+ ///
+ /// Connection parameters used to identify and access the target.
+ ///
+ ///
+ /// An URI identifying the request task to enable concurrent execution.
+ ///
+ ///
+ /// A function performing assessment operation for given target.
+ ///
+ ///
+ /// Returns for given target.
+ ///
+ internal async Task> CallAssessmentEngine(
+ AssessmentParams requestParams,
+ ConnectParams connectParams,
+ string taskUri,
+ Func>> assessmentFunc)
+ where TResult : AssessmentItemInfo
+
+ {
+ var result = new AssessmentResult
+ {
+ ApiVersion = ApiVersion
+ };
+
+ await ConnectionService.Connect(connectParams);
+
+ var connection = await ConnectionService.Instance.GetOrOpenConnection(taskUri, ConnectionType.Query);
+
+ try
+ {
+ var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
+ var hostInfo = ReliableConnectionHelper.GetServerHostInfo(connection);
+
+ var server = new SqlObjectLocator
+ {
+ Connection = connection,
+ EngineEdition = GetEngineEdition(serverInfo.EngineEditionId),
+ Name = serverInfo.ServerName,
+ ServerName = serverInfo.ServerName,
+ Type = SqlObjectType.Server,
+ Urn = serverInfo.ServerName,
+ Version = Version.Parse(serverInfo.ServerVersion),
+ Platform = hostInfo.Platform
+ };
+
+ switch (requestParams.TargetType)
+ {
+ case SqlObjectType.Server:
+ Logger.Write(
+ TraceEventType.Verbose,
+ $"SQL Assessment: running an operation on a server, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
+
+ result.Items.AddRange(await assessmentFunc(server));
+
+ Logger.Write(
+ TraceEventType.Verbose,
+ $"SQL Assessment: finished an operation on a server, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
+ break;
+ case SqlObjectType.Database:
+ var db = GetDatabaseLocator(server, connection.Database);
+ Logger.Write(
+ TraceEventType.Verbose,
+ $"SQL Assessment: running an operation on a database, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
+
+ result.Items.AddRange(await assessmentFunc(db));
+
+ Logger.Write(
+ TraceEventType.Verbose,
+ $"SQL Assessment: finished an operation on a database, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
+ break;
+ }
+
+ result.Success = true;
+ }
+ finally
+ {
+ ActiveRequests.TryRemove(taskUri, out _);
+ ConnectionService.Disconnect(new DisconnectParams { OwnerUri = taskUri, Type = null });
+ }
+
+ return result;
+ }
+
+ ///
+ /// Invokes SQL Assessment and formats results.
+ ///
+ ///
+ /// A sequence of target servers or databases to be assessed.
+ ///
+ ///
+ /// Returns a
+ /// containing assessment results.
+ ///
+ ///
+ /// Internal for testing
+ ///
+ internal async Task> InvokeSqlAssessment(SqlObjectLocator target)
+ {
+ var resultsList = await Engine.GetAssessmentResultsList(target);
+ Logger.Write(TraceEventType.Verbose, $"SQL Assessment: got {resultsList.Count} results.");
+
+ return resultsList.Select(TranslateAssessmentResult).ToList();
+ }
+
+ ///
+ /// Gets the list of checks for given target servers or databases.
+ ///
+ ///
+ /// A sequence of target servers or databases.
+ ///
+ ///
+ /// Returns an
+ /// containing checks available for given .
+ ///
+ internal Task> GetAssessmentItems(SqlObjectLocator target)
+ {
+ var result = new List();
+
+ var resultsList = Engine.GetChecks(target).ToList();
+ Logger.Write(TraceEventType.Verbose, $"SQL Assessment: got {resultsList.Count} items.");
+
+ foreach (var r in resultsList)
+ {
+ var targetName = target.Type != SqlObjectType.Server
+ ? $"{target.ServerName}:{target.Name}"
+ : target.Name;
+
+ var item = new CheckInfo()
+ {
+ CheckId = r.Id,
+ Description = r.Description,
+ DisplayName = r.DisplayName,
+ HelpLink = r.HelpLink,
+ Level = r.Level.ToString(),
+ TargetName = targetName,
+ Tags = r.Tags.ToArray(),
+ TargetType = target.Type,
+ RulesetName = Engine.Configuration.DefaultRuleset.Name,
+ RulesetVersion = Engine.Configuration.DefaultRuleset.Version.ToString()
+ };
+
+ result.Add(item);
+ }
+
+ return Task.FromResult(result);
+ }
+
+ private AssessmentResultItem TranslateAssessmentResult(IAssessmentResult r)
+ {
+ var item = new AssessmentResultItem
+ {
+ CheckId = r.Check.Id,
+ Description = r.Check.Description,
+ DisplayName = r.Check.DisplayName,
+ HelpLink = r.Check.HelpLink,
+ Level = r.Check.Level.ToString(),
+ Message = r.Message,
+ TargetName = r.TargetPath,
+ Tags = r.Check.Tags.ToArray(),
+ TargetType = r.TargetType,
+ RulesetVersion = Engine.Configuration.DefaultRuleset.Version.ToString(),
+ RulesetName = Engine.Configuration.DefaultRuleset.Name,
+ Timestamp = r.Timestamp
+ };
+
+ if (r is IAssessmentNote)
+ {
+ item.Kind = AssessmentResultItemKind.Note;
+ }
+ else if (r is IAssessmentWarning)
+ {
+ item.Kind = AssessmentResultItemKind.Warning;
+ }
+ else if (r is IAssessmentError)
+ {
+ item.Kind = AssessmentResultItemKind.Error;
+ }
+
+ return item;
+ }
+
+ ///
+ /// Constructs a for specified database.
+ ///
+ /// Target server locator.
+ /// Target database name.
+ /// Returns a locator for target database.
+ private static SqlObjectLocator GetDatabaseLocator(SqlObjectLocator server, string databaseName)
+ {
+ return new SqlObjectLocator
+ {
+ Connection = server.Connection,
+ EngineEdition = server.EngineEdition,
+ Name = databaseName,
+ Platform = server.Platform,
+ ServerName = server.Name,
+ Type = SqlObjectType.Database,
+ Urn = $"{server.Name}:{databaseName}",
+ Version = server.Version
+ };
+ }
+
+ ///
+ /// Converts numeric of engine edition
+ /// returned by SERVERPROPERTY('EngineEdition').
+ ///
+ ///
+ /// A number returned by SERVERPROPERTY('EngineEdition').
+ ///
+ /// Engine edition is not supported.
+ ///
+ /// Returns a
+ /// corresponding to the .
+ ///
+ private static SqlEngineEdition GetEngineEdition(int representation)
+ {
+ switch (representation)
+ {
+ case 1: return SqlEngineEdition.PersonalOrDesktopEngine;
+ case 2: return SqlEngineEdition.Standard;
+ case 3: return SqlEngineEdition.Enterprise;
+ case 4: return SqlEngineEdition.Express;
+ case 5: return SqlEngineEdition.AzureDatabase;
+ case 6: return SqlEngineEdition.DataWarehouse;
+ case 7: return SqlEngineEdition.StretchDatabase;
+ case 8: return SqlEngineEdition.ManagedInstance;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(representation),
+ SR.SqlAssessmentUnsuppoertedEdition(representation));
+ }
+ }
+
+ #endregion
+
+ #region IDisposable Implementation
+
+ private bool disposed;
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private void Dispose(bool disposing)
+ {
+ if (disposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ foreach (var request in ActiveRequests)
+ {
+ request.Value.Dispose();
+ }
+
+ ActiveRequests.Clear();
+ }
+
+ disposed = true;
+ }
+
+ ~SqlAssessmentService()
+ {
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlAssessment/SqlAssessmentServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlAssessment/SqlAssessmentServiceTests.cs
index e99ecc19..2364916e 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlAssessment/SqlAssessmentServiceTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlAssessment/SqlAssessmentServiceTests.cs
@@ -1,225 +1,225 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Threading.Tasks;
-
-using Microsoft.SqlServer.Management.Assessment;
-using Microsoft.SqlTools.ServiceLayer.Connection;
-using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
-using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
-using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
-using Microsoft.SqlTools.ServiceLayer.SqlAssessment;
-using Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts;
-using Microsoft.SqlTools.ServiceLayer.Test.Common;
-using NUnit.Framework;
-
-namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlAssessment
-{
- public class SqlAssessmentServiceTests
- {
- private delegate Task> AssessmentMethod(SqlObjectLocator locator);
-
- private static readonly string[] AllowedSeverityLevels = { "Information", "Warning", "Critical" };
-
- [Test]
- public async Task InvokeSqlAssessmentServerTest()
- {
- var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo("master");
-
- var connection = liveConnection.ConnectionInfo.AllConnections.FirstOrDefault();
- Debug.Assert(connection != null, "Live connection is always expected providing a connection");
-
- var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
-
- var response = await CallAssessment(
- nameof(SqlAssessmentService.InvokeSqlAssessment),
- SqlObjectType.Server,
- liveConnection);
-
- Assert.Multiple(() =>
- {
- Assert.That(response.Items.Select(i => i.Message), Has.All.Not.Null.Or.Empty);
- Assert.That(response.Items.Select(i => i.TargetName), Has.All.EqualTo(serverInfo.ServerName));
- foreach (var i in response.Items.Where(i => i.Kind == 0))
- {
- AssertInfoPresent(i);
- }
- });
- }
-
- [Test]
- public async Task GetAssessmentItemsServerTest()
- {
- var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo("master");
-
- var connection = liveConnection.ConnectionInfo.AllConnections.FirstOrDefault();
- Debug.Assert(connection != null, "Live connection is always expected providing a connection");
-
- var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
-
- var response = await CallAssessment(
- nameof(SqlAssessmentService.GetAssessmentItems),
- SqlObjectType.Server,
- liveConnection);
-
- Assert.Multiple(() =>
- {
- Assert.That(response.Items.Select(i => i.TargetName), Has.All.EqualTo(serverInfo.ServerName));
- foreach (var i in response.Items)
- {
- AssertInfoPresent(i);
- }
- });
- }
-
- [Test]
- public async Task GetAssessmentItemsDatabaseTest()
- {
- const string DatabaseName = "tempdb";
- var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(DatabaseName);
- var response = await CallAssessment(
- nameof(SqlAssessmentService.GetAssessmentItems),
- SqlObjectType.Database,
- liveConnection);
-
- Assert.Multiple(() =>
- {
- Assert.That(response.Items.Select(i => i.TargetName), Has.All.EndsWith(":" + DatabaseName));
- foreach (var i in response.Items)
- {
- AssertInfoPresent(i);
- }
- });
- }
-
- [Test]
- public async Task InvokeSqlAssessmentIDatabaseTest()
- {
- const string DatabaseName = "tempdb";
- var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(DatabaseName);
- var response = await CallAssessment(
- nameof(SqlAssessmentService.InvokeSqlAssessment),
- SqlObjectType.Database,
- liveConnection);
-
- Assert.Multiple(() =>
- {
- Assert.That(response.Items.Select(i => i.Message), Has.All.Not.Null.Or.Empty);
- Assert.That(response.Items.Select(i => i.TargetName), Has.All.EndsWith(":" + DatabaseName));
- foreach (var i in response.Items.Where(i => i.Kind == 0))
- {
- AssertInfoPresent(i);
- }
- });
- }
-
- private static async Task> CallAssessment(
- string methodName,
- SqlObjectType sqlObjectType,
- LiveConnectionHelper.TestConnectionResult liveConnection)
- where TResult : AssessmentItemInfo
- {
- var connInfo = liveConnection.ConnectionInfo;
-
- AssessmentResult response;
-
- using (var service = new SqlAssessmentService(
- TestServiceProvider.Instance.ConnectionService,
- TestServiceProvider.Instance.WorkspaceService))
- {
- AddTestRules(service);
-
- string randomUri = Guid.NewGuid().ToString();
- AssessmentParams requestParams =
- new AssessmentParams { OwnerUri = randomUri, TargetType = sqlObjectType };
- ConnectParams connectParams = new ConnectParams
- {
- OwnerUri = requestParams.OwnerUri,
- Connection = connInfo.ConnectionDetails,
- Type = ConnectionType.Default
- };
-
- var methodInfo = typeof(SqlAssessmentService).GetMethod(
- methodName,
- BindingFlags.Instance | BindingFlags.NonPublic);
-
- Assert.NotNull(methodInfo);
-
- var func = (AssessmentMethod)Delegate.CreateDelegate(
- typeof(AssessmentMethod),
- service,
- methodInfo);
-
- response = await service.CallAssessmentEngine(
- requestParams,
- connectParams,
- randomUri,
- t => func(t));
- }
-
- Assert.NotNull(response);
- if (response.Success)
- {
- Assert.That(response.Items.Select(i => i.TargetType), Has.All.EqualTo(sqlObjectType));
- Assert.That(response.Items.Select(i => i.Level), Has.All.AnyOf(AllowedSeverityLevels));
- }
-
- return response;
- }
-
- private static void AddTestRules(SqlAssessmentService service)
- {
- const string TestRuleset = @"
- {
- 'name': 'Tags & Checks',
- 'version': '0.3',
- 'schemaVersion': '1.0',
- 'rules': [
- {
- 'id': 'ServerRule',
- 'itemType': 'definition',
- 'tags': [ 'Test' ],
- 'displayName': 'Test server check',
- 'description': 'This check always fails for testing purposes.',
- 'message': 'This check intentionally fails',
- 'target': { 'type': 'Server' }
- },
- {
- 'id': 'DatabaseRule',
- 'itemType': 'definition',
- 'tags': [ 'Test' ],
- 'displayName': 'Test server check',
- 'description': 'This check always fails for testing purposes.',
- 'message': 'This check intentionally fails',
- 'target': { 'type': 'Database' }
- }
- ]
- }
-";
- using (var reader = new StringReader(TestRuleset))
- {
- service.Engine.PushRuleFactoryJson(reader);
- }
- }
-
- private void AssertInfoPresent(AssessmentItemInfo item)
- {
- Assert.Multiple(() =>
- {
- Assert.That(item.CheckId, Is.Not.Null.Or.Empty);
- Assert.That(item.DisplayName, Is.Not.Null.Or.Empty);
- Assert.That(item.Description, Is.Not.Null.Or.Empty);
- Assert.NotNull(item.Tags);
- Assert.That(item.Tags, Has.All.Not.Null.Or.Empty);
- });
- }
- }
-}
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+
+using Microsoft.SqlServer.Management.Assessment;
+using Microsoft.SqlTools.ServiceLayer.Connection;
+using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
+using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
+using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
+using Microsoft.SqlTools.ServiceLayer.SqlAssessment;
+using Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts;
+using Microsoft.SqlTools.ServiceLayer.Test.Common;
+using NUnit.Framework;
+
+namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlAssessment
+{
+ public class SqlAssessmentServiceTests
+ {
+ private delegate Task> AssessmentMethod(SqlObjectLocator locator);
+
+ private static readonly string[] AllowedSeverityLevels = { "Information", "Warning", "Critical" };
+
+ [Test]
+ public async Task InvokeSqlAssessmentServerTest()
+ {
+ var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo("master");
+
+ var connection = liveConnection.ConnectionInfo.AllConnections.FirstOrDefault();
+ Debug.Assert(connection != null, "Live connection is always expected providing a connection");
+
+ var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
+
+ var response = await CallAssessment(
+ nameof(SqlAssessmentService.InvokeSqlAssessment),
+ SqlObjectType.Server,
+ liveConnection);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(response.Items.Select(i => i.Message), Has.All.Not.Null.Or.Empty);
+ Assert.That(response.Items.Select(i => i.TargetName), Has.All.EqualTo(serverInfo.ServerName));
+ foreach (var i in response.Items.Where(i => i.Kind == 0))
+ {
+ AssertInfoPresent(i);
+ }
+ });
+ }
+
+ [Test]
+ public async Task GetAssessmentItemsServerTest()
+ {
+ var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo("master");
+
+ var connection = liveConnection.ConnectionInfo.AllConnections.FirstOrDefault();
+ Debug.Assert(connection != null, "Live connection is always expected providing a connection");
+
+ var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
+
+ var response = await CallAssessment(
+ nameof(SqlAssessmentService.GetAssessmentItems),
+ SqlObjectType.Server,
+ liveConnection);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(response.Items.Select(i => i.TargetName), Has.All.EqualTo(serverInfo.ServerName));
+ foreach (var i in response.Items)
+ {
+ AssertInfoPresent(i);
+ }
+ });
+ }
+
+ [Test]
+ public async Task GetAssessmentItemsDatabaseTest()
+ {
+ const string DatabaseName = "tempdb";
+ var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(DatabaseName);
+ var response = await CallAssessment(
+ nameof(SqlAssessmentService.GetAssessmentItems),
+ SqlObjectType.Database,
+ liveConnection);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(response.Items.Select(i => i.TargetName), Has.All.EndsWith(":" + DatabaseName));
+ foreach (var i in response.Items)
+ {
+ AssertInfoPresent(i);
+ }
+ });
+ }
+
+ [Test]
+ public async Task InvokeSqlAssessmentIDatabaseTest()
+ {
+ const string DatabaseName = "tempdb";
+ var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(DatabaseName);
+ var response = await CallAssessment(
+ nameof(SqlAssessmentService.InvokeSqlAssessment),
+ SqlObjectType.Database,
+ liveConnection);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(response.Items.Select(i => i.Message), Has.All.Not.Null.Or.Empty);
+ Assert.That(response.Items.Select(i => i.TargetName), Has.All.EndsWith(":" + DatabaseName));
+ foreach (var i in response.Items.Where(i => i.Kind == 0))
+ {
+ AssertInfoPresent(i);
+ }
+ });
+ }
+
+ private static async Task> CallAssessment(
+ string methodName,
+ SqlObjectType sqlObjectType,
+ LiveConnectionHelper.TestConnectionResult liveConnection)
+ where TResult : AssessmentItemInfo
+ {
+ var connInfo = liveConnection.ConnectionInfo;
+
+ AssessmentResult response;
+
+ using (var service = new SqlAssessmentService(
+ TestServiceProvider.Instance.ConnectionService,
+ TestServiceProvider.Instance.WorkspaceService))
+ {
+ AddTestRules(service);
+
+ string randomUri = Guid.NewGuid().ToString();
+ AssessmentParams requestParams =
+ new AssessmentParams { OwnerUri = randomUri, TargetType = sqlObjectType };
+ ConnectParams connectParams = new ConnectParams
+ {
+ OwnerUri = requestParams.OwnerUri,
+ Connection = connInfo.ConnectionDetails,
+ Type = ConnectionType.Default
+ };
+
+ var methodInfo = typeof(SqlAssessmentService).GetMethod(
+ methodName,
+ BindingFlags.Instance | BindingFlags.NonPublic);
+
+ Assert.NotNull(methodInfo);
+
+ var func = (AssessmentMethod)Delegate.CreateDelegate(
+ typeof(AssessmentMethod),
+ service,
+ methodInfo);
+
+ response = await service.CallAssessmentEngine(
+ requestParams,
+ connectParams,
+ randomUri,
+ t => func(t));
+ }
+
+ Assert.NotNull(response);
+ if (response.Success)
+ {
+ Assert.That(response.Items.Select(i => i.TargetType), Has.All.EqualTo(sqlObjectType));
+ Assert.That(response.Items.Select(i => i.Level), Has.All.AnyOf(AllowedSeverityLevels));
+ }
+
+ return response;
+ }
+
+ private static void AddTestRules(SqlAssessmentService service)
+ {
+ const string TestRuleset = @"
+ {
+ 'name': 'Tags & Checks',
+ 'version': '0.3',
+ 'schemaVersion': '1.0',
+ 'rules': [
+ {
+ 'id': 'ServerRule',
+ 'itemType': 'definition',
+ 'tags': [ 'Test' ],
+ 'displayName': 'Test server check',
+ 'description': 'This check always fails for testing purposes.',
+ 'message': 'This check intentionally fails',
+ 'target': { 'type': 'Server' }
+ },
+ {
+ 'id': 'DatabaseRule',
+ 'itemType': 'definition',
+ 'tags': [ 'Test' ],
+ 'displayName': 'Test server check',
+ 'description': 'This check always fails for testing purposes.',
+ 'message': 'This check intentionally fails',
+ 'target': { 'type': 'Database' }
+ }
+ ]
+ }
+";
+ using (var reader = new StringReader(TestRuleset))
+ {
+ service.Engine.PushRuleFactoryJson(reader);
+ }
+ }
+
+ private void AssertInfoPresent(AssessmentItemInfo item)
+ {
+ Assert.Multiple(() =>
+ {
+ Assert.That(item.CheckId, Is.Not.Null.Or.Empty);
+ Assert.That(item.DisplayName, Is.Not.Null.Or.Empty);
+ Assert.That(item.Description, Is.Not.Null.Or.Empty);
+ Assert.NotNull(item.Tags);
+ Assert.That(item.Tags, Has.All.Not.Null.Or.Empty);
+ });
+ }
+ }
+}
diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/SqlAssessment/GenerateScriptOperationTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/SqlAssessment/GenerateScriptOperationTests.cs
index b70c9198..14b77613 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/SqlAssessment/GenerateScriptOperationTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/SqlAssessment/GenerateScriptOperationTests.cs
@@ -1,157 +1,159 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.SqlServer.Management.Assessment;
-using Microsoft.SqlTools.ServiceLayer.SqlAssessment;
-using Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts;
-using Microsoft.SqlTools.ServiceLayer.TaskServices;
-using Moq;
-using NUnit.Framework;
-
-namespace Microsoft.SqlTools.ServiceLayer.UnitTests.SqlAssessment
-{
- public class GenerateScriptOperationTests
- {
- private static readonly GenerateScriptParams SampleParams = new GenerateScriptParams
- {
- Items = new List
- {
- new AssessmentResultItem
- {
- CheckId = "C1",
- Description = "Desc1",
- DisplayName = "DN1",
- HelpLink = "HL1",
- Kind = AssessmentResultItemKind.Note,
- Level = "Information",
- Message = "Msg'1",
- TargetName = "proj[*]_dev",
- TargetType = SqlObjectType.Server,
- Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.Zero),
- RulesetName = "Microsoft Ruleset",
- RulesetVersion = "1.3"
- },
- new AssessmentResultItem
- {
- CheckId = "C-2",
- Description = "Desc2",
- DisplayName = "D N2",
- HelpLink = "http://HL2",
- Kind = AssessmentResultItemKind.Warning,
- Level = "Warning",
- Message = "Msg'1",
- TargetName = "proj[*]_devW",
- TargetType = SqlObjectType.Database,
- Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.FromHours(3)),
- RulesetName = "Microsoft Ruleset",
- RulesetVersion = "1.3"
- },
- new AssessmentResultItem
- {
- CheckId = "C'3",
- Description = "Des'c3",
- DisplayName = "D'N1",
- HelpLink = "HL'1",
- Kind = AssessmentResultItemKind.Error,
- Level = "Critical",
- Message = "Msg'1",
- TargetName = "proj[*]_devE",
- TargetType = SqlObjectType.Server,
- Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.FromMinutes(-90)),
- RulesetName = "Microsoft Ruleset",
- RulesetVersion = "1.3"
- },
- new AssessmentResultItem
- {
- CheckId = "C-2",
- Description = "Desc2",
- DisplayName = "D N2",
- HelpLink = "http://HL2",
- Kind = AssessmentResultItemKind.Note,
- Level = "Warning",
- Message = "Msg'1",
- TargetName = "proj[*]_dev",
- TargetType = SqlObjectType.Database,
- Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.FromHours(3)),
- RulesetName = "Microsoft Ruleset",
- RulesetVersion = "1.3"
- },
- new AssessmentResultItem
- {
- CheckId = "C'3",
- Description = "Des'c3",
- DisplayName = "D'N1",
- HelpLink = "HL'1",
- Kind = AssessmentResultItemKind.Note,
- Level = "Critical",
- Message = "Msg'1",
- TargetName = "proj[*]_dev",
- TargetType = SqlObjectType.Server,
- Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.FromMinutes(-90)),
- RulesetName = "Microsoft Ruleset",
- RulesetVersion = "1.3"
- }
- }
- };
-
- private const string SampleScript =
- @"IF (NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'AssessmentResult'))
-BEGIN
- CREATE TABLE [dbo].[AssessmentResult](
- [CheckName] [nvarchar](max) NOT NULL,
- [CheckId] [nvarchar](max) NOT NULL,
- [RulesetName] [nvarchar](max) NOT NULL,
- [RulesetVersion] [nvarchar](max) NOT NULL,
- [Severity] [nvarchar](max) NOT NULL,
- [Message] [nvarchar](max) NOT NULL,
- [TargetPath] [nvarchar](max) NOT NULL,
- [TargetType] [nvarchar](max) NOT NULL,
- [HelpLink] [nvarchar](max) NOT NULL,
- [Timestamp] [datetimeoffset](7) NOT NULL
- )
-END
-GO
-INSERT INTO [dbo].[AssessmentResult] ([CheckName],[CheckId],[RulesetName],[RulesetVersion],[Severity],[Message],[TargetPath],[TargetType],[HelpLink],[Timestamp])
-VALUES
-('DN1','C1','Microsoft Ruleset','1.3','Information','Msg''1','proj[*]_dev','Server','HL1','2001-05-25 01:42:00.000 +00:00'),
-('D N2','C-2','Microsoft Ruleset','1.3','Warning','Msg''1','proj[*]_dev','Database','http://HL2','2001-05-25 01:42:00.000 +03:00'),
-('D''N1','C''3','Microsoft Ruleset','1.3','Critical','Msg''1','proj[*]_dev','Server','HL''1','2001-05-25 01:42:00.000 -01:30')";
-
- [Test]
- public void GenerateScriptTest()
- {
- var scriptText = GenerateScriptOperation.GenerateScript(SampleParams, CancellationToken.None);
- Assert.AreEqual(SampleScript, scriptText);
- }
-
- [Test]
- public void ExecuteTest()
- {
- var subject = new GenerateScriptOperation(SampleParams);
- var taskMetadata = new TaskMetadata();
- using (var sqlTask = new SqlTask(taskMetadata, DummyOpFunction, DummyOpFunction))
- {
- subject.SqlTask = sqlTask;
- sqlTask.ScriptAdded += ValidateScriptAdded;
- subject.Execute(TaskExecutionMode.Script);
- }
- }
-
- private void ValidateScriptAdded(object sender, TaskEventArgs e)
- {
- Assert.AreEqual(SqlTaskStatus.Succeeded, e.TaskData.Status);
- Assert.AreEqual(SampleScript, e.TaskData.Script);
- }
-
- private static Task DummyOpFunction(SqlTask _)
- {
- return Task.FromResult(new TaskResult() {TaskStatus = SqlTaskStatus.Succeeded});
- }
- }
-}
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.SqlServer.Management.Assessment;
+using Microsoft.SqlTools.ServiceLayer.SqlAssessment;
+using Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts;
+using Microsoft.SqlTools.ServiceLayer.TaskServices;
+using Moq;
+using NUnit.Framework;
+
+namespace Microsoft.SqlTools.ServiceLayer.UnitTests.SqlAssessment
+{
+ public class GenerateScriptOperationTests
+ {
+ private static readonly GenerateScriptParams SampleParams = new GenerateScriptParams
+ {
+ Items = new List
+ {
+ new AssessmentResultItem
+ {
+ CheckId = "C1",
+ Description = "Desc1",
+ DisplayName = "DN1",
+ HelpLink = "HL1",
+ Kind = AssessmentResultItemKind.Note,
+ Level = "Information",
+ Message = "Msg'1",
+ TargetName = "proj[*]_dev",
+ TargetType = SqlObjectType.Server,
+ Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.Zero),
+ RulesetName = "Microsoft Ruleset",
+ RulesetVersion = "1.3"
+ },
+ new AssessmentResultItem
+ {
+ CheckId = "C-2",
+ Description = "Desc2",
+ DisplayName = "D N2",
+ HelpLink = "http://HL2",
+ Kind = AssessmentResultItemKind.Warning,
+ Level = "Warning",
+ Message = "Msg'1",
+ TargetName = "proj[*]_devW",
+ TargetType = SqlObjectType.Database,
+ Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.FromHours(3)),
+ RulesetName = "Microsoft Ruleset",
+ RulesetVersion = "1.3"
+ },
+ new AssessmentResultItem
+ {
+ CheckId = "C'3",
+ Description = "Des'c3",
+ DisplayName = "D'N1",
+ HelpLink = "HL'1",
+ Kind = AssessmentResultItemKind.Error,
+ Level = "Critical",
+ Message = "Msg'1",
+ TargetName = "proj[*]_devE",
+ TargetType = SqlObjectType.Server,
+ Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.FromMinutes(-90)),
+ RulesetName = "Microsoft Ruleset",
+ RulesetVersion = "1.3"
+ },
+ new AssessmentResultItem
+ {
+ CheckId = "C-2",
+ Description = "Desc2",
+ DisplayName = "D N2",
+ HelpLink = "http://HL2",
+ Kind = AssessmentResultItemKind.Note,
+ Level = "Warning",
+ Message = "Msg'1",
+ TargetName = "proj[*]_dev",
+ TargetType = SqlObjectType.Database,
+ Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.FromHours(3)),
+ RulesetName = "Microsoft Ruleset",
+ RulesetVersion = "1.3"
+ },
+ new AssessmentResultItem
+ {
+ CheckId = "C'3",
+ Description = "Des'c3",
+ DisplayName = "D'N1",
+ HelpLink = "HL'1",
+ Kind = AssessmentResultItemKind.Note,
+ Level = "Critical",
+ Message = "Msg'1",
+ TargetName = "proj[*]_dev",
+ TargetType = SqlObjectType.Server,
+ Timestamp = new DateTimeOffset(2001, 5, 25, 13, 42, 00, TimeSpan.FromMinutes(-90)),
+ RulesetName = "Microsoft Ruleset",
+ RulesetVersion = "1.3"
+ }
+ }
+ };
+
+ private const string SampleScript =
+ @"IF (NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'AssessmentResult'))
+BEGIN
+ CREATE TABLE [dbo].[AssessmentResult](
+ [CheckName] [nvarchar](max),
+ [CheckId] [nvarchar](max),
+ [RulesetName] [nvarchar](max),
+ [RulesetVersion] [nvarchar](max),
+ [Severity] [nvarchar](max),
+ [Message] [nvarchar](max),
+ [TargetPath] [nvarchar](max),
+ [TargetType] [nvarchar](max),
+ [HelpLink] [nvarchar](max),
+ [Timestamp] [datetimeoffset](7)
+ )
+END
+GO
+INSERT INTO [dbo].[AssessmentResult] ([CheckName],[CheckId],[RulesetName],[RulesetVersion],[Severity],[Message],[TargetPath],[TargetType],[HelpLink],[Timestamp])
+ SELECT rpt.[CheckName],rpt.[CheckId],rpt.[RulesetName],rpt.[RulesetVersion],rpt.[Severity],rpt.[Message],rpt.[TargetPath],rpt.[TargetType],rpt.[HelpLink],rpt.[Timestamp]
+ FROM (VALUES
+ ('DN1','C1','Microsoft Ruleset','1.3','Information','Msg''1','proj[*]_dev','Server','HL1','2001-05-25 01:42:00.000 +00:00'),
+ ('D N2','C-2','Microsoft Ruleset','1.3','Warning','Msg''1','proj[*]_dev','Database','http://HL2','2001-05-25 01:42:00.000 +03:00'),
+ ('D''N1','C''3','Microsoft Ruleset','1.3','Critical','Msg''1','proj[*]_dev','Server','HL''1','2001-05-25 01:42:00.000 -01:30')
+ ) rpt([CheckName],[CheckId],[RulesetName],[RulesetVersion],[Severity],[Message],[TargetPath],[TargetType],[HelpLink],[Timestamp])";
+
+ [Test]
+ public void GenerateScriptTest()
+ {
+ var scriptText = GenerateScriptOperation.GenerateScript(SampleParams, CancellationToken.None);
+ Assert.AreEqual(SampleScript, scriptText);
+ }
+
+ [Test]
+ public void ExecuteTest()
+ {
+ var subject = new GenerateScriptOperation(SampleParams);
+ var taskMetadata = new TaskMetadata();
+ using (var sqlTask = new SqlTask(taskMetadata, DummyOpFunction, DummyOpFunction))
+ {
+ subject.SqlTask = sqlTask;
+ sqlTask.ScriptAdded += ValidateScriptAdded;
+ subject.Execute(TaskExecutionMode.Script);
+ }
+ }
+
+ private void ValidateScriptAdded(object sender, TaskEventArgs e)
+ {
+ Assert.AreEqual(SqlTaskStatus.Succeeded, e.TaskData.Status);
+ Assert.AreEqual(SampleScript, e.TaskData.Script);
+ }
+
+ private static Task DummyOpFunction(SqlTask _)
+ {
+ return Task.FromResult(new TaskResult() {TaskStatus = SqlTaskStatus.Succeeded});
+ }
+ }
+}