diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs index da9816d8..46bbc286 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs @@ -37,12 +37,14 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { ConnectionService = ConnectionService.Instance; WorkspaceService = WorkspaceService.Instance; + Settings = new SqlToolsSettings(); } internal QueryExecutionService(ConnectionService connService, WorkspaceService workspaceService) { ConnectionService = connService; WorkspaceService = workspaceService; + Settings = new SqlToolsSettings(); } #endregion @@ -105,7 +107,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution private readonly Lazy> queries = new Lazy>(() => new ConcurrentDictionary()); - private SqlToolsSettings Settings => WorkspaceService.Instance.CurrentSettings; + /// + /// Settings that will be used to execute queries. Internal for unit testing + /// + internal SqlToolsSettings Settings { get; set; } #endregion @@ -134,11 +139,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution }); // Register a handler for when the configuration changes - WorkspaceService.RegisterConfigChangeCallback((oldSettings, newSettings, eventContext) => - { - Settings.QueryExecutionSettings.Update(newSettings.QueryExecutionSettings); - return Task.FromResult(0); - }); + WorkspaceService.RegisterConfigChangeCallback(UpdateSettings); } #region Request Handlers @@ -410,13 +411,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution } // Retrieve the current settings for executing the query with - QueryExecutionSettings settings = WorkspaceService.CurrentSettings.QueryExecutionSettings; + QueryExecutionSettings querySettings = Settings.QueryExecutionSettings; // Apply execution parameter settings - settings.ExecutionPlanOptions = executeParams.ExecutionPlanOptions; + querySettings.ExecutionPlanOptions = executeParams.ExecutionPlanOptions; // If we can't add the query now, it's assumed the query is in progress - Query newQuery = new Query(GetSqlText(executeParams), connectionInfo, settings, BufferFileFactory); + Query newQuery = new Query(GetSqlText(executeParams), connectionInfo, querySettings, BufferFileFactory); if (!ActiveQueries.TryAdd(executeParams.OwnerUri, newQuery)) { await failureAction(SR.QueryServiceQueryInProgress); @@ -591,6 +592,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution throw new InvalidCastException("Invalid request type"); } + /// Internal for testing purposes + internal Task UpdateSettings(SqlToolsSettings newSettings, SqlToolsSettings oldSettings, EventContext eventContext) + { + Settings.QueryExecutionSettings.Update(newSettings.QueryExecutionSettings); + return Task.FromResult(0); + } + #endregion #region IDisposable Implementation diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs index 93f677ed..539c6f83 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs @@ -126,6 +126,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext /// /// Gets or sets the query execution settings /// + [JsonProperty("query")] public QueryExecutionSettings QueryExecutionSettings { get; set; } /// diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/SettingsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/SettingsTests.cs new file mode 100644 index 00000000..ecdac161 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/SettingsTests.cs @@ -0,0 +1,92 @@ +// +// 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.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.QueryExecution; +using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; +using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution +{ + public class SettingsTests + { + [Fact] + public void ValidateQueryExecuteDefaults() + { + // If: I create a new settings object + var sqlToolsSettings = new SqlToolsSettings(); + + // Then: The default values should be as expected + Assert.Equal("GO", sqlToolsSettings.QueryExecutionSettings.BatchSeparator); + Assert.Equal(ushort.MaxValue, sqlToolsSettings.QueryExecutionSettings.MaxCharsToStore); + Assert.Equal(2*1024*1024, sqlToolsSettings.QueryExecutionSettings.MaxXmlCharsToStore); + Assert.False(sqlToolsSettings.QueryExecutionSettings.ExecutionPlanOptions.IncludeActualExecutionPlanXml); + Assert.False(sqlToolsSettings.QueryExecutionSettings.ExecutionPlanOptions.IncludeEstimatedExecutionPlanXml); + Assert.True(sqlToolsSettings.QueryExecutionSettings.DisplayBitAsNumber); + } + + [Fact] + public void ValidateSettingsParsedFromJson() + { + // NOTE: Only testing displayBitAsNumber for now because it is the only one piped through + const string settingsJson = @"{" + + @"""params"": {" + + @"""mssql"": {" + + @"""query"": {" + + @"displayBitAsNumber: false" + + @"}" + + @"}" + + @"}" + + @"}"; + + // If: I parse the settings JSON object + JObject message = JObject.Parse(settingsJson); + JToken messageParams; + Assert.True(message.TryGetValue("params", out messageParams)); + SqlToolsSettings sqlToolsSettings = messageParams.ToObject(); + + // Then: The values defined in the JSON should propagate to the setting object + Assert.False(sqlToolsSettings.QueryExecutionSettings.DisplayBitAsNumber); + } + + [Fact] + public void ValidateSettingsObjectUpdates() + { + // If: I update a settings object with a new settings object + var qes = new QueryExecutionService(null, null); + SqlToolsSettings settings = new SqlToolsSettings() + { + SqlTools = new SqlToolsSettingsValues + { + QueryExecutionSettings = new QueryExecutionSettings + { + DisplayBitAsNumber = false, + MaxXmlCharsToStore = 1, + MaxCharsToStore = 1, + ExecutionPlanOptions = new ExecutionPlanOptions + { + IncludeActualExecutionPlanXml = true, + IncludeEstimatedExecutionPlanXml = true + }, + BatchSeparator = "YO" + } + } + + }; + qes.UpdateSettings(settings, null, new EventContext()); + + // Then: The settings object should match what it was updated to + Assert.False(qes.Settings.QueryExecutionSettings.DisplayBitAsNumber); + Assert.True(qes.Settings.QueryExecutionSettings.ExecutionPlanOptions.IncludeActualExecutionPlanXml); + Assert.True(qes.Settings.QueryExecutionSettings.ExecutionPlanOptions.IncludeEstimatedExecutionPlanXml); + Assert.Equal(1, qes.Settings.QueryExecutionSettings.MaxCharsToStore); + Assert.Equal(1, qes.Settings.QueryExecutionSettings.MaxXmlCharsToStore); + Assert.Equal("YO", qes.Settings.QueryExecutionSettings.BatchSeparator); + } + + } +}