mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Adding project property support to SqlProj service (#1883)
* Nuget update * Updating nuget * implementation * GetProperties test * Adding SetDatabaseSource * adding comment * Nuget update * PR feedback * Fixing cross-plat path tests * Updating to signed nuget * fixing None test
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
<PackageReference Update="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" Version="1.1.1" />
|
||||
<PackageReference Update="Microsoft.SqlServer.Management.SmoMetadataProvider" Version="170.12.0" />
|
||||
<PackageReference Update="Microsoft.SqlServer.DacFx" Version="161.8406.0-preview" />
|
||||
<PackageReference Update="Microsoft.SqlServer.DacFx.Projects" Version="161.8093.0-alpha" />
|
||||
<PackageReference Update="Microsoft.SqlServer.DacFx.Projects" Version="161.8416.0-alpha" />
|
||||
<PackageReference Update="Microsoft.Azure.Kusto.Data" Version="9.0.4" />
|
||||
<PackageReference Update="Microsoft.Azure.Kusto.Language" Version="9.0.4" />
|
||||
<PackageReference Update="Microsoft.SqlServer.Assessment" Version="[1.1.17]" />
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// 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;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the cross-platform compatibility status for a project
|
||||
/// </summary>
|
||||
public class GetProjectPropertiesRequest
|
||||
{
|
||||
public static readonly RequestType<SqlProjectParams, GetProjectPropertiesResult> Type = RequestType<SqlProjectParams, GetProjectPropertiesResult>.Create("sqlProjects/getProjectProperties");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result containing project properties contained in the .sqlproj XML
|
||||
/// </summary>
|
||||
public class GetProjectPropertiesResult : ResultStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// GUID for the SQL project
|
||||
/// </summary>
|
||||
public string ProjectGuid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Build configuration, defaulted to Debug if not specified
|
||||
/// </summary>
|
||||
public string Configuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Build platform, defaulted to AnyCPU if not specified
|
||||
/// </summary>
|
||||
public string Platform { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output path for build, defaulted to "bin/Debug" if not specified.
|
||||
/// May be absolute or relative.
|
||||
/// </summary>
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default collation for the project, defaulted to SQL_Latin1_General_CP1_CI_AS if not specified
|
||||
/// </summary>
|
||||
public string DefaultCollation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Source of the database schema, used in telemetry
|
||||
/// </summary>
|
||||
public string? DatabaseSource { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
#nullable disable
|
||||
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters for setting the DatabaseSource property of a .sqlproj file
|
||||
/// </summary>
|
||||
public class SetDatabaseSourceParams : SqlProjectParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Source of the database schema, used in telemetry
|
||||
/// </summary>
|
||||
public string DatabaseSource { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the DatabaseSource property of a .sqlproj file
|
||||
/// </summary>
|
||||
public class SetDatabaseSourceRequest
|
||||
{
|
||||
public static readonly RequestType<SetDatabaseSourceParams, ResultStatus> Type = RequestType<SetDatabaseSourceParams, ResultStatus>.Create("sqlProjects/setDatabaseSource");
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects
|
||||
serviceHost.SetRequestHandler(CreateSqlProjectRequest.Type, HandleCreateSqlProjectRequest, isParallelProcessingSupported: true);
|
||||
serviceHost.SetRequestHandler(GetCrossPlatformCompatibilityRequest.Type, HandleGetCrossPlatformCompatibilityRequest, isParallelProcessingSupported: true);
|
||||
serviceHost.SetRequestHandler(UpdateProjectForCrossPlatformRequest.Type, HandleUpdateProjectForCrossPlatformRequest, isParallelProcessingSupported: false);
|
||||
serviceHost.SetRequestHandler(GetProjectPropertiesRequest.Type, HandleGetProjectPropertiesRequest, isParallelProcessingSupported: true);
|
||||
serviceHost.SetRequestHandler(SetDatabaseSourceRequest.Type, HandleSetDatabaseSourceRequest, isParallelProcessingSupported: false);
|
||||
|
||||
// SQL object script functions
|
||||
serviceHost.SetRequestHandler(GetSqlObjectScriptsRequest.Type, HandleGetSqlObjectScriptsRequest, isParallelProcessingSupported: true);
|
||||
@@ -133,6 +135,31 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects
|
||||
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).UpdateForCrossPlatform(), requestContext);
|
||||
}
|
||||
|
||||
internal async Task HandleGetProjectPropertiesRequest(SqlProjectParams requestParams, RequestContext<GetProjectPropertiesResult> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(() =>
|
||||
{
|
||||
SqlProjectProperties props = GetProject(requestParams.ProjectUri).Properties;
|
||||
|
||||
return new GetProjectPropertiesResult()
|
||||
{
|
||||
Success = true,
|
||||
ErrorMessage = null,
|
||||
ProjectGuid = props.ProjectGuid,
|
||||
Configuration = props.Configuration,
|
||||
Platform = props.Platform,
|
||||
OutputPath = props.OutputPath,
|
||||
DefaultCollation = props.DefaultCollation,
|
||||
DatabaseSource = props.DatabaseSource,
|
||||
};
|
||||
}, requestContext);
|
||||
}
|
||||
|
||||
internal async Task HandleSetDatabaseSourceRequest(SetDatabaseSourceParams requestParams, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).Properties.DatabaseSource = requestParams.DatabaseSource, requestContext);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Script/folder functions
|
||||
@@ -310,7 +337,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects
|
||||
|
||||
#endregion
|
||||
|
||||
#region Database Reference functions
|
||||
#region Database reference functions
|
||||
|
||||
internal async Task HandleGetDatabaseReferencesRequest(SqlProjectParams requestParams, RequestContext<GetDatabaseReferencesResult> requestContext)
|
||||
{
|
||||
@@ -459,7 +486,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects
|
||||
{
|
||||
if (!Projects.ContainsKey(projectUri))
|
||||
{
|
||||
Projects[projectUri] = new SqlProject(projectUri);
|
||||
Projects[projectUri] = SqlProject.OpenProject(projectUri);
|
||||
}
|
||||
|
||||
return Projects[projectUri];
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
|
||||
|
||||
// Validate moving a SQL object script
|
||||
string movedScriptRelativePath = @"SubPath\MyRenamedTable.sql";
|
||||
string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), movedScriptRelativePath);
|
||||
string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), FileUtils.NormalizePath(movedScriptRelativePath));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(movedScriptAbsolutePath)!);
|
||||
|
||||
requestMock = new();
|
||||
@@ -254,7 +254,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
|
||||
|
||||
// Validate moving a None script
|
||||
string movedScriptRelativePath = @"SubPath\RenamedNoneIncludeFile.json";
|
||||
string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), movedScriptRelativePath);
|
||||
string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), FileUtils.NormalizePath(movedScriptRelativePath));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(movedScriptAbsolutePath)!);
|
||||
|
||||
requestMock = new();
|
||||
@@ -343,7 +343,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
|
||||
|
||||
// Validate moving a pre-deployment object script
|
||||
string movedScriptRelativePath = @"SubPath\RenamedPreDeploymentScript.sql";
|
||||
string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), movedScriptRelativePath);
|
||||
string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), FileUtils.NormalizePath(movedScriptRelativePath));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(movedScriptAbsolutePath)!);
|
||||
|
||||
requestMock = new();
|
||||
@@ -432,7 +432,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
|
||||
|
||||
// Validate moving a post-deployment object script
|
||||
string movedScriptRelativePath = @"SubPath\RenamedPostDeploymentScript.sql";
|
||||
string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), movedScriptRelativePath);
|
||||
string movedScriptAbsolutePath = Path.Join(Path.GetDirectoryName(projectUri), FileUtils.NormalizePath(movedScriptRelativePath));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(movedScriptAbsolutePath)!);
|
||||
|
||||
requestMock = new();
|
||||
@@ -823,6 +823,53 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
|
||||
Assert.IsTrue(((GetCrossPlatformCompatibilityResult)getRequestMock.Result).IsCrossPlatformCompatible, "Input file should be cross-platform compatible after conversion");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestProjectProperties()
|
||||
{
|
||||
SqlProjectsService service = new();
|
||||
string projectUri = await service.CreateSqlProject();
|
||||
|
||||
MockRequest<GetProjectPropertiesResult> mock = new();
|
||||
|
||||
await service.HandleGetProjectPropertiesRequest(new SqlProjectParams()
|
||||
{
|
||||
ProjectUri = projectUri
|
||||
}, mock.Object);
|
||||
|
||||
mock.AssertSuccess(nameof(service.HandleGetProjectPropertiesRequest));
|
||||
|
||||
Assert.IsTrue(Guid.TryParse(mock.Result.ProjectGuid, out _), $"{mock.Result.ProjectGuid} should be set");
|
||||
Assert.AreEqual("AnyCPU", mock.Result.Platform);
|
||||
Assert.AreEqual("Debug", mock.Result.Configuration);
|
||||
Assert.AreEqual(@"bin\Debug\", mock.Result.OutputPath); // default value is normalized to Windows slashes
|
||||
Assert.AreEqual("SQL_Latin1_General_CP1_CI_AS", mock.Result.DefaultCollation);
|
||||
Assert.IsNull(mock.Result.DatabaseSource, nameof(mock.Result.DatabaseSource)); // validate DatabaseSource is null when the tag isn't present
|
||||
|
||||
// Validate that DatabaseSource can be set when the tag doesn't exist
|
||||
|
||||
MockRequest<ResultStatus> setSourceMock = new();
|
||||
await service.HandleSetDatabaseSourceRequest(new SetDatabaseSourceParams()
|
||||
{
|
||||
ProjectUri = projectUri,
|
||||
DatabaseSource = "TestSource"
|
||||
}, setSourceMock.Object);
|
||||
|
||||
setSourceMock.AssertSuccess(nameof(service.HandleSetDatabaseSourceRequest));
|
||||
Assert.AreEqual("TestSource", service.Projects[projectUri].Properties.DatabaseSource);
|
||||
|
||||
// Validate DatabaseSource is read when it has a value
|
||||
|
||||
mock = new();
|
||||
|
||||
await service.HandleGetProjectPropertiesRequest(new SqlProjectParams()
|
||||
{
|
||||
ProjectUri = projectUri
|
||||
}, mock.Object);
|
||||
|
||||
mock.AssertSuccess(nameof(service.HandleGetProjectPropertiesRequest));
|
||||
Assert.AreEqual("TestSource", mock.Result.DatabaseSource);
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
private async Task<(SqlProjectsService Service, string ProjectUri, SqlCmdVariable DatabaseVar, SqlCmdVariable ServerVar)> SetUpDatabaseReferenceTest()
|
||||
|
||||
@@ -80,13 +80,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes Windows, Unix, and mixed paths to the same slash direction, specified by <paramref name="separatorType"/>
|
||||
/// Normalizes Windows, Unix, and mixed paths to the same slash direction, specified by <paramref name="separatorType"/>.
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="separatorType">Win32NT for \, Unix for /</param>
|
||||
/// <param name="separatorType">Win32NT for \, Unix for /. If not set, path will be normalized to the current platform.</param>
|
||||
/// <returns></returns>
|
||||
public static string NormalizePath(string path, PlatformID separatorType)
|
||||
public static string NormalizePath(string path, PlatformID? separatorType = null)
|
||||
{
|
||||
separatorType ??= Environment.OSVersion.Platform;
|
||||
|
||||
return separatorType switch
|
||||
{
|
||||
PlatformID.Win32NT => path.Contains('/')
|
||||
|
||||
Reference in New Issue
Block a user