mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-25 17:24:17 -05:00
Adding new setting for numeric or text bit display (#243)
Adding a new setting to query execution setting that will change the display value we generate for `BIT` columns. The new setting is `DefaultDisplayBitAsNumber`. If true, bit columns will be displayed as 1 or 0. If false, they'll be displayed as true or false. The default value is true, to keep parity with SSMS behavior. Enables us to solve https://github.com/Microsoft/vscode-mssql/issues/690 and https://github.com/Microsoft/vscode-mssql/issues/513
This commit is contained in:
@@ -58,7 +58,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <summary>
|
||||
/// Special action which this batch performed
|
||||
/// </summary>
|
||||
private SpecialAction specialAction;
|
||||
private readonly SpecialAction specialAction;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// Localized timestamp for when the execution completed.
|
||||
/// Stored in UTC ISO 8601 format; should be localized before displaying to any user
|
||||
/// </summary>
|
||||
public string ExecutionEndTimeStamp { get { return executionEndTime.ToString("o"); } }
|
||||
public string ExecutionEndTimeStamp => executionEndTime.ToString("o");
|
||||
|
||||
/// <summary>
|
||||
/// Localized timestamp for how long it took for the execution to complete
|
||||
@@ -146,7 +146,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// Localized timestamp for when the execution began.
|
||||
/// Stored in UTC ISO 8601 format; should be localized before displaying to any user
|
||||
/// </summary>
|
||||
public string ExecutionStartTimeStamp { get { return executionStartTime.ToString("o"); } }
|
||||
public string ExecutionStartTimeStamp => executionStartTime.ToString("o");
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this batch encountered an error that halted execution
|
||||
@@ -161,15 +161,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <summary>
|
||||
/// Ordinal of the batch in the query
|
||||
/// </summary>
|
||||
public int Id { get; private set; }
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The result sets of the batch execution
|
||||
/// </summary>
|
||||
public IList<ResultSet> ResultSets
|
||||
{
|
||||
get { return resultSets; }
|
||||
}
|
||||
public IList<ResultSet> ResultSets => resultSets;
|
||||
|
||||
/// <summary>
|
||||
/// Property for generating a set result set summaries from the result sets
|
||||
@@ -381,7 +378,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// Generates an execution plan
|
||||
/// </summary>
|
||||
/// <param name="resultSetIndex">The index for selecting the result set</param>
|
||||
/// <returns>An exeuction plan object</returns>
|
||||
/// <returns>An execution plan object</returns>
|
||||
public Task<ExecutionPlan> GetExecutionPlan(int resultSetIndex)
|
||||
{
|
||||
ResultSet targetResultSet;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
{
|
||||
@@ -17,6 +18,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Settings for query execution
|
||||
/// </summary>
|
||||
public QueryExecutionSettings QueryExecutionSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parameters for the save as CSV request
|
||||
/// </summary>
|
||||
@@ -41,7 +47,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// <returns>Stream reader</returns>
|
||||
public IFileStreamReader GetReader(string fileName)
|
||||
{
|
||||
return new ServiceBufferFileStreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read));
|
||||
return new ServiceBufferFileStreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read), QueryExecutionSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
{
|
||||
@@ -14,6 +15,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Settings for query execution
|
||||
/// </summary>
|
||||
public QueryExecutionSettings QueryExecutionSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parameters for the save as JSON request
|
||||
/// </summary>
|
||||
@@ -28,7 +34,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
[Obsolete]
|
||||
public string CreateFile()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -38,7 +44,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// <returns>Stream reader</returns>
|
||||
public IFileStreamReader GetReader(string fileName)
|
||||
{
|
||||
return new ServiceBufferFileStreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read));
|
||||
return new ServiceBufferFileStreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read), QueryExecutionSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//
|
||||
|
||||
using System.IO;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
{
|
||||
@@ -15,14 +16,9 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of characters to store from long text fields
|
||||
/// The settings for query execution
|
||||
/// </summary>
|
||||
public int MaxCharsToStore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of characters to store from xml fields
|
||||
/// </summary>
|
||||
public int MaxXmlCharsToStore { get; set; }
|
||||
public QueryExecutionSettings ExecutionSettings { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -43,7 +39,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// <returns>A <see cref="ServiceBufferFileStreamReader"/></returns>
|
||||
public IFileStreamReader GetReader(string fileName)
|
||||
{
|
||||
return new ServiceBufferFileStreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read));
|
||||
return new ServiceBufferFileStreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read), ExecutionSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// <returns>A <see cref="ServiceBufferFileStreamWriter"/></returns>
|
||||
public IFileStreamWriter GetWriter(string fileName)
|
||||
{
|
||||
return new ServiceBufferFileStreamWriter(new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite), MaxCharsToStore, MaxXmlCharsToStore);
|
||||
return new ServiceBufferFileStreamWriter(new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite), ExecutionSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,6 +9,8 @@ using System.Data.SqlTypes;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
{
|
||||
@@ -30,6 +32,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
|
||||
private byte[] buffer;
|
||||
|
||||
private readonly QueryExecutionSettings executionSettings;
|
||||
|
||||
private readonly Stream fileStream;
|
||||
|
||||
private readonly Dictionary<Type, Func<long, DbColumnWrapper, FileStreamReadResult>> readMethods;
|
||||
@@ -40,8 +44,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// Constructs a new ServiceBufferFileStreamReader and initializes its state
|
||||
/// </summary>
|
||||
/// <param name="stream">The filestream to read from</param>
|
||||
public ServiceBufferFileStreamReader(Stream stream)
|
||||
{
|
||||
/// <param name="settings">The query execution settings</param>
|
||||
public ServiceBufferFileStreamReader(Stream stream, QueryExecutionSettings settings)
|
||||
{
|
||||
Validate.IsNotNull(nameof(stream), stream);
|
||||
Validate.IsNotNull(nameof(settings), settings);
|
||||
|
||||
// Open file for reading/writing
|
||||
if (!stream.CanRead || !stream.CanSeek)
|
||||
{
|
||||
@@ -49,6 +57,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
}
|
||||
fileStream = stream;
|
||||
|
||||
executionSettings = settings;
|
||||
|
||||
// Create internal buffer
|
||||
buffer = new byte[DefaultBufferSize];
|
||||
|
||||
@@ -259,7 +269,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// <returns>A bool</returns>
|
||||
internal FileStreamReadResult ReadBoolean(long fileOffset)
|
||||
{
|
||||
return ReadCellHelper(fileOffset, length => buffer[0] == 0x1);
|
||||
// Override the stringifier with numeric values if the user prefers that
|
||||
return ReadCellHelper(fileOffset, length => buffer[0] == 0x1,
|
||||
toStringFunc: val => executionSettings.DisplayBitAsNumber
|
||||
? val ? "1" : "0"
|
||||
: val.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -505,10 +519,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// <summary>
|
||||
/// <see cref="LengthLength"/> + <see cref="ValueLength"/>
|
||||
/// </summary>
|
||||
public int TotalLength
|
||||
{
|
||||
get { return LengthLength + ValueLength; }
|
||||
}
|
||||
public int TotalLength => LengthLength + ValueLength;
|
||||
}
|
||||
|
||||
#region IDisposable Implementation
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
@@ -24,8 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
#region Member Variables
|
||||
|
||||
private readonly Stream fileStream;
|
||||
private readonly int maxCharsToStore;
|
||||
private readonly int maxXmlCharsToStore;
|
||||
private readonly QueryExecutionSettings executionSettings;
|
||||
|
||||
private byte[] byteBuffer;
|
||||
private readonly short[] shortBuffer;
|
||||
@@ -46,16 +46,19 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
/// Constructs a new writer
|
||||
/// </summary>
|
||||
/// <param name="stream">The file wrapper to use as the underlying file stream</param>
|
||||
/// <param name="maxCharsToStore">Maximum number of characters to store for long text fields</param>
|
||||
/// <param name="maxXmlCharsToStore">Maximum number of characters to store for XML fields</param>
|
||||
public ServiceBufferFileStreamWriter(Stream stream, int maxCharsToStore, int maxXmlCharsToStore)
|
||||
/// <param name="settings">The query execution settings</param>
|
||||
public ServiceBufferFileStreamWriter(Stream stream, QueryExecutionSettings settings)
|
||||
{
|
||||
Validate.IsNotNull(nameof(stream), stream);
|
||||
Validate.IsNotNull(nameof(settings), settings);
|
||||
|
||||
// open file for reading/writing
|
||||
if (!stream.CanWrite || !stream.CanSeek)
|
||||
{
|
||||
throw new InvalidOperationException("Stream must be writable and seekable.");
|
||||
}
|
||||
fileStream = stream;
|
||||
executionSettings = settings;
|
||||
|
||||
// create internal buffer
|
||||
byteBuffer = new byte[DefaultBufferLength];
|
||||
@@ -69,10 +72,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
doubleBuffer = new double[1];
|
||||
floatBuffer = new float[1];
|
||||
|
||||
// Store max chars to store
|
||||
this.maxCharsToStore = maxCharsToStore;
|
||||
this.maxXmlCharsToStore = maxXmlCharsToStore;
|
||||
|
||||
// Define what methods to use to write a type to the file
|
||||
writeMethods = new Dictionary<Type, Func<object, int>>
|
||||
{
|
||||
@@ -145,18 +144,18 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
|
||||
// this is a long field
|
||||
if (ci.IsBytes)
|
||||
{
|
||||
values[i] = reader.GetBytesWithMaxCapacity(i, maxCharsToStore);
|
||||
values[i] = reader.GetBytesWithMaxCapacity(i, executionSettings.MaxCharsToStore);
|
||||
}
|
||||
else if (ci.IsChars)
|
||||
{
|
||||
Debug.Assert(maxCharsToStore > 0);
|
||||
values[i] = reader.GetCharsWithMaxCapacity(i,
|
||||
ci.IsXml ? maxXmlCharsToStore : maxCharsToStore);
|
||||
int maxChars = ci.IsXml
|
||||
? executionSettings.MaxXmlCharsToStore
|
||||
: executionSettings.MaxCharsToStore;
|
||||
values[i] = reader.GetCharsWithMaxCapacity(i, maxChars);
|
||||
}
|
||||
else if (ci.IsXml)
|
||||
{
|
||||
Debug.Assert(maxXmlCharsToStore > 0);
|
||||
values[i] = reader.GetXmlWithMaxCapacity(i, maxXmlCharsToStore);
|
||||
values[i] = reader.GetXmlWithMaxCapacity(i, executionSettings.MaxXmlCharsToStore);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -53,16 +53,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// </summary>
|
||||
private bool hasExecuteBeenCalled;
|
||||
|
||||
/// <summary>
|
||||
/// Settings for query runtime
|
||||
/// </summary>
|
||||
private QueryExecutionSettings querySettings;
|
||||
|
||||
/// <summary>
|
||||
/// Streaming output factory for the query
|
||||
/// </summary>
|
||||
private IFileStreamFactory streamOutputFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the new database if the database name was changed in the query
|
||||
/// </summary>
|
||||
@@ -109,8 +99,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
QueryText = queryText;
|
||||
editorConnection = connection;
|
||||
cancellationSource = new CancellationTokenSource();
|
||||
querySettings = settings;
|
||||
streamOutputFactory = outputFactory;
|
||||
|
||||
// Process the query into batches
|
||||
BatchParserWrapper parser = new BatchParserWrapper();
|
||||
@@ -135,16 +123,16 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
if (DoesSupportExecutionPlan(connection))
|
||||
{
|
||||
// Checking settings for execution plan options
|
||||
if (querySettings.ExecutionPlanOptions.IncludeEstimatedExecutionPlanXml)
|
||||
if (settings.ExecutionPlanOptions.IncludeEstimatedExecutionPlanXml)
|
||||
{
|
||||
// Enable set showplan xml
|
||||
addBatch(string.Format(SetShowPlanXml, On), BeforeBatches, streamOutputFactory);
|
||||
addBatch(string.Format(SetShowPlanXml, Off), AfterBatches, streamOutputFactory);
|
||||
AddBatch(string.Format(SetShowPlanXml, On), BeforeBatches, outputFactory);
|
||||
AddBatch(string.Format(SetShowPlanXml, Off), AfterBatches, outputFactory);
|
||||
}
|
||||
else if (querySettings.ExecutionPlanOptions.IncludeActualExecutionPlanXml)
|
||||
else if (settings.ExecutionPlanOptions.IncludeActualExecutionPlanXml)
|
||||
{
|
||||
addBatch(string.Format(SetStatisticsXml, On), BeforeBatches, streamOutputFactory);
|
||||
addBatch(string.Format(SetStatisticsXml, Off), AfterBatches, streamOutputFactory);
|
||||
AddBatch(string.Format(SetStatisticsXml, On), BeforeBatches, outputFactory);
|
||||
AddBatch(string.Format(SetStatisticsXml, Off), AfterBatches, outputFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,11 +170,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// </summary>
|
||||
public event QueryAsyncEventHandler QueryFailed;
|
||||
|
||||
/// <summary>
|
||||
/// Callback for when the query connection has failed
|
||||
/// </summary>
|
||||
public event QueryAsyncErrorEventHandler QueryConnectionException;
|
||||
|
||||
/// <summary>
|
||||
/// Event to be called when a resultset has completed.
|
||||
/// </summary>
|
||||
@@ -459,7 +442,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <summary>
|
||||
/// Function to add a new batch to a Batch set
|
||||
/// </summary>
|
||||
private void addBatch(string query, List<Batch> batchSet, IFileStreamFactory outputFactory)
|
||||
private static void AddBatch(string query, ICollection<Batch> batchSet, IFileStreamFactory outputFactory)
|
||||
{
|
||||
batchSet.Add(new Batch(query, null, batchSet.Count, outputFactory));
|
||||
}
|
||||
|
||||
@@ -64,11 +64,14 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
{
|
||||
get
|
||||
{
|
||||
return BufferFileStreamFactory ?? (BufferFileStreamFactory = new ServiceBufferFileStreamFactory
|
||||
if (BufferFileStreamFactory == null)
|
||||
{
|
||||
MaxCharsToStore = Settings.SqlTools.QueryExecutionSettings.MaxCharsToStore,
|
||||
MaxXmlCharsToStore = Settings.SqlTools.QueryExecutionSettings.MaxXmlCharsToStore
|
||||
});
|
||||
BufferFileStreamFactory = new ServiceBufferFileStreamFactory
|
||||
{
|
||||
ExecutionSettings = Settings.QueryExecutionSettings
|
||||
};
|
||||
}
|
||||
return BufferFileStreamFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +298,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
// Use the default CSV file factory if we haven't overridden it
|
||||
IFileStreamFactory csvFactory = CsvFileFactory ?? new SaveAsCsvFileStreamFactory
|
||||
{
|
||||
SaveRequestParams = saveParams
|
||||
SaveRequestParams = saveParams,
|
||||
QueryExecutionSettings = Settings.QueryExecutionSettings
|
||||
};
|
||||
await SaveResultsHelper(saveParams, requestContext, csvFactory);
|
||||
}
|
||||
@@ -309,7 +313,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
// Use the default JSON file factory if we haven't overridden it
|
||||
IFileStreamFactory jsonFactory = JsonFileFactory ?? new SaveAsJsonFileStreamFactory
|
||||
{
|
||||
SaveRequestParams = saveParams
|
||||
SaveRequestParams = saveParams,
|
||||
QueryExecutionSettings = Settings.QueryExecutionSettings
|
||||
};
|
||||
await SaveResultsHelper(saveParams, requestContext, jsonFactory);
|
||||
}
|
||||
@@ -452,20 +457,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
await eventSender.SendEvent(QueryCompleteEvent.Type, eventParams);
|
||||
};
|
||||
|
||||
Query.QueryAsyncErrorEventHandler errorCallback = async errorMessage =>
|
||||
{
|
||||
// Send back the error message
|
||||
QueryCompleteParams eventParams = new QueryCompleteParams
|
||||
{
|
||||
OwnerUri = ownerUri,
|
||||
//Message = errorMessage
|
||||
};
|
||||
await eventSender.SendEvent(QueryCompleteEvent.Type, eventParams);
|
||||
};
|
||||
|
||||
query.QueryCompleted += callback;
|
||||
query.QueryFailed += callback;
|
||||
query.QueryConnectionException += errorCallback;
|
||||
|
||||
// Setup the batch callbacks
|
||||
Batch.BatchAsyncEventHandler batchStartCallback = async b =>
|
||||
|
||||
@@ -25,8 +25,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
#region Constants
|
||||
|
||||
// Column names of 'for xml' and 'for json' queries
|
||||
private const string NameOfForXMLColumn = "XML_F52E2B61-18A1-11d1-B105-00805F49916B";
|
||||
private const string NameOfForJSONColumn = "JSON_F52E2B61-18A1-11d1-B105-00805F49916B";
|
||||
private const string NameOfForXmlColumn = "XML_F52E2B61-18A1-11d1-B105-00805F49916B";
|
||||
private const string NameOfForJsonColumn = "JSON_F52E2B61-18A1-11d1-B105-00805F49916B";
|
||||
private const string YukonXmlShowPlanColumn = "Microsoft SQL Server 2005 XML Showplan";
|
||||
|
||||
#endregion
|
||||
@@ -72,7 +72,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <summary>
|
||||
/// The special action which applied to this result set
|
||||
/// </summary>
|
||||
private SpecialAction specialAction;
|
||||
private readonly SpecialAction specialAction;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -251,7 +251,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <returns>An execution plan object</returns>
|
||||
public Task<ExecutionPlan> GetExecutionPlan()
|
||||
{
|
||||
// Proccess the action just incase is hasn't been yet
|
||||
// Process the action just incase is hasn't been yet
|
||||
ProcessSpecialAction();
|
||||
|
||||
// Sanity check to make sure that the results have been read beforehand
|
||||
@@ -260,7 +260,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
throw new InvalidOperationException(SR.QueryServiceResultSetNotRead);
|
||||
}
|
||||
// Check that we this result set contains a showplan
|
||||
else if (!specialAction.ExpectYukonXMLShowPlan)
|
||||
if (!specialAction.ExpectYukonXMLShowPlan)
|
||||
{
|
||||
throw new Exception(SR.QueryServiceExecutionPlanNotFound);
|
||||
}
|
||||
@@ -268,7 +268,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
|
||||
return Task.Factory.StartNew(() =>
|
||||
{
|
||||
string content = null;
|
||||
string content;
|
||||
string format = null;
|
||||
|
||||
using (IFileStreamReader fileStreamReader = fileStreamFactory.GetReader(outputFileName))
|
||||
@@ -333,6 +333,15 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the contents of this result set to a file using the IFileStreamFactory provided
|
||||
/// </summary>
|
||||
/// <param name="saveParams">Parameters for saving the results to a file</param>
|
||||
/// <param name="fileFactory">
|
||||
/// Factory for creating a stream reader/writer combo for writing results to disk
|
||||
/// </param>
|
||||
/// <param name="successHandler">Handler for a successful write of all rows</param>
|
||||
/// <param name="failureHandler">Handler for unsuccessful write of all rows</param>
|
||||
public void SaveAs(SaveResultsRequestParams saveParams, IFileStreamFactory fileFactory,
|
||||
SaveAsAsyncEventHandler successHandler, SaveAsFailureAsyncEventHandler failureHandler)
|
||||
{
|
||||
@@ -475,13 +484,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
|
||||
if (Columns?.Length == 1 && RowCount != 0)
|
||||
{
|
||||
if (Columns[0].ColumnName.Equals(NameOfForXMLColumn, StringComparison.Ordinal))
|
||||
if (Columns[0].ColumnName.Equals(NameOfForXmlColumn, StringComparison.Ordinal))
|
||||
{
|
||||
Columns[0].IsXml = true;
|
||||
isSingleColumnXmlJsonResultSet = true;
|
||||
RowCount = 1;
|
||||
}
|
||||
else if (Columns[0].ColumnName.Equals(NameOfForJSONColumn, StringComparison.Ordinal))
|
||||
else if (Columns[0].ColumnName.Equals(NameOfForJsonColumn, StringComparison.Ordinal))
|
||||
{
|
||||
Columns[0].IsJson = true;
|
||||
isSingleColumnXmlJsonResultSet = true;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// 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.QueryExecution.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
||||
@@ -33,12 +34,17 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
||||
/// Default selection of returning an actual XML showplan with all batches
|
||||
/// Do not return any execution plan by default
|
||||
/// </summary>
|
||||
private ExecutionPlanOptions DefaultExecutionPlanOptions = new ExecutionPlanOptions()
|
||||
private static readonly ExecutionPlanOptions DefaultExecutionPlanOptions = new ExecutionPlanOptions
|
||||
{
|
||||
IncludeActualExecutionPlanXml = false,
|
||||
IncludeEstimatedExecutionPlanXml = false
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Default option for displaying a bit column as a number. (defacto standard as per SSMS)
|
||||
/// </summary>
|
||||
private const bool DefaultDisplayBitAsNumber = true;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Member Variables
|
||||
@@ -51,6 +57,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
||||
|
||||
private ExecutionPlanOptions? executionPlanOptions;
|
||||
|
||||
private bool? displayBitAsNumber;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
@@ -64,24 +72,46 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
||||
set { batchSeparator = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of characters to store in temp file for long character fields and binary
|
||||
/// fields. Will use a default if a value was not configured.
|
||||
/// </summary>
|
||||
public int MaxCharsToStore
|
||||
{
|
||||
get { return maxCharsToStore ?? DefaultMaxCharsToStore; }
|
||||
set { maxCharsToStore = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of characters to store in temp file for XML columns. Will use a default
|
||||
/// value if one was not configured.
|
||||
/// </summary>
|
||||
public int MaxXmlCharsToStore
|
||||
{
|
||||
get { return maxXmlCharsToStore ?? DefaultMaxXmlCharsToStore; }
|
||||
set { maxXmlCharsToStore = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options for returning execution plans when executing queries
|
||||
/// </summary>
|
||||
public ExecutionPlanOptions ExecutionPlanOptions
|
||||
{
|
||||
get { return executionPlanOptions ?? DefaultExecutionPlanOptions; }
|
||||
set { executionPlanOptions = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines how to generate display value for bit columns. If <c>true</c>, bit columns
|
||||
/// will be rendered as "1" or "0". If <c>false</c>, bit columns will be rendered as
|
||||
/// "true" or "false"
|
||||
/// </summary>
|
||||
public bool DisplayBitAsNumber
|
||||
{
|
||||
get { return displayBitAsNumber ?? DefaultDisplayBitAsNumber; }
|
||||
set { displayBitAsNumber = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
@@ -96,6 +126,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
||||
MaxCharsToStore = newSettings.MaxCharsToStore;
|
||||
MaxXmlCharsToStore = newSettings.MaxXmlCharsToStore;
|
||||
ExecutionPlanOptions = newSettings.ExecutionPlanOptions;
|
||||
DisplayBitAsNumber = newSettings.DisplayBitAsNumber;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -111,9 +111,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
|
||||
return fileName;
|
||||
});
|
||||
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
|
||||
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output])));
|
||||
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output]), new QueryExecutionSettings()));
|
||||
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
|
||||
.Returns<string>(output => new ServiceBufferFileStreamWriter(new MemoryStream(storage[output]), 1024, 1024));
|
||||
.Returns<string>(output => new ServiceBufferFileStreamWriter(new MemoryStream(storage[output]), new QueryExecutionSettings()));
|
||||
|
||||
return mock.Object;
|
||||
}
|
||||
|
||||
@@ -148,9 +148,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
||||
return fileName;
|
||||
});
|
||||
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
|
||||
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output])));
|
||||
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output]), new QueryExecutionSettings()));
|
||||
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
|
||||
.Returns<string>(output => new ServiceBufferFileStreamWriter(new MemoryStream(storage[output]), 1024, 1024));
|
||||
.Returns<string>(output => new ServiceBufferFileStreamWriter(new MemoryStream(storage[output]), new QueryExecutionSettings()));
|
||||
|
||||
return mock.Object;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Utility;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
@@ -20,6 +21,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
{
|
||||
public class ReaderWriterPairTest
|
||||
{
|
||||
[Fact]
|
||||
public void ReaderStreamNull()
|
||||
{
|
||||
// If: I create a service buffer file stream reader with a null stream
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => new ServiceBufferFileStreamReader(null, new QueryExecutionSettings()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReaderSettingsNull()
|
||||
{
|
||||
// If: I create a service buffer file stream reader with null settings
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => new ServiceBufferFileStreamReader(Stream.Null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReaderInvalidStreamCannotRead()
|
||||
{
|
||||
@@ -30,7 +47,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
invalidStream.SetupGet(s => s.CanSeek).Returns(true);
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
ServiceBufferFileStreamReader obj = new ServiceBufferFileStreamReader(invalidStream.Object);
|
||||
ServiceBufferFileStreamReader obj = new ServiceBufferFileStreamReader(invalidStream.Object, new QueryExecutionSettings());
|
||||
obj.Dispose();
|
||||
});
|
||||
}
|
||||
@@ -45,11 +62,27 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
invalidStream.SetupGet(s => s.CanSeek).Returns(false);
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
ServiceBufferFileStreamReader obj = new ServiceBufferFileStreamReader(invalidStream.Object);
|
||||
ServiceBufferFileStreamReader obj = new ServiceBufferFileStreamReader(invalidStream.Object, new QueryExecutionSettings());
|
||||
obj.Dispose();
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriterStreamNull()
|
||||
{
|
||||
// If: I create a service buffer file stream writer with a null stream
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => new ServiceBufferFileStreamWriter(null, new QueryExecutionSettings()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriterSettingsNull()
|
||||
{
|
||||
// If: I create a service buffer file stream writer with null settings
|
||||
// Then: It should throw an exception
|
||||
Assert.Throws<ArgumentNullException>(() => new ServiceBufferFileStreamWriter(Stream.Null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriterInvalidStreamCannotWrite()
|
||||
{
|
||||
@@ -60,7 +93,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
invalidStream.SetupGet(s => s.CanSeek).Returns(true);
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
ServiceBufferFileStreamWriter obj = new ServiceBufferFileStreamWriter(invalidStream.Object, 1024, 1024);
|
||||
ServiceBufferFileStreamWriter obj = new ServiceBufferFileStreamWriter(invalidStream.Object, new QueryExecutionSettings());
|
||||
obj.Dispose();
|
||||
});
|
||||
}
|
||||
@@ -75,20 +108,24 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
invalidStream.SetupGet(s => s.CanSeek).Returns(false);
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
ServiceBufferFileStreamWriter obj = new ServiceBufferFileStreamWriter(invalidStream.Object, 1024, 1024);
|
||||
ServiceBufferFileStreamWriter obj = new ServiceBufferFileStreamWriter(invalidStream.Object, new QueryExecutionSettings());
|
||||
obj.Dispose();
|
||||
});
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
|
||||
private static string VerifyReadWrite<T>(int valueLength, T value, Func<ServiceBufferFileStreamWriter, T, int> writeFunc, Func<ServiceBufferFileStreamReader, FileStreamReadResult> readFunc)
|
||||
private static string VerifyReadWrite<T>(int valueLength, T value,
|
||||
Func<ServiceBufferFileStreamWriter, T, int> writeFunc,
|
||||
Func<ServiceBufferFileStreamReader, FileStreamReadResult> readFunc,
|
||||
QueryExecutionSettings overrideSettings = null)
|
||||
{
|
||||
// Setup: Create a mock file stream
|
||||
byte[] storage = new byte[8192];
|
||||
overrideSettings = overrideSettings ?? new QueryExecutionSettings();
|
||||
|
||||
// If:
|
||||
// ... I write a type T to the writer
|
||||
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(new MemoryStream(storage), 10, 10))
|
||||
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(new MemoryStream(storage), overrideSettings))
|
||||
{
|
||||
int writtenBytes = writeFunc(writer, value);
|
||||
Assert.Equal(valueLength, writtenBytes);
|
||||
@@ -96,7 +133,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
|
||||
// ... And read the type T back
|
||||
FileStreamReadResult outValue;
|
||||
using (ServiceBufferFileStreamReader reader = new ServiceBufferFileStreamReader(new MemoryStream(storage)))
|
||||
using (ServiceBufferFileStreamReader reader = new ServiceBufferFileStreamReader(new MemoryStream(storage), overrideSettings))
|
||||
{
|
||||
outValue = readFunc(reader);
|
||||
}
|
||||
@@ -166,11 +203,29 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void Boolean(bool value)
|
||||
[InlineData(true, true)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, false)]
|
||||
public void Boolean(bool value, bool preferNumeric)
|
||||
{
|
||||
VerifyReadWrite(sizeof(bool) + 1, value, (writer, val) => writer.WriteBoolean(val), reader => reader.ReadBoolean(0));
|
||||
string displayValue = VerifyReadWrite(sizeof(bool) + 1, value,
|
||||
(writer, val) => writer.WriteBoolean(val),
|
||||
reader => reader.ReadBoolean(0),
|
||||
new QueryExecutionSettings {DisplayBitAsNumber = preferNumeric}
|
||||
);
|
||||
|
||||
// Validate the display value
|
||||
if (preferNumeric)
|
||||
{
|
||||
int output;
|
||||
Assert.True(int.TryParse(displayValue, out output));
|
||||
}
|
||||
else
|
||||
{
|
||||
bool output;
|
||||
Assert.True(bool.TryParse(displayValue, out output));
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -396,7 +451,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
{
|
||||
// If:
|
||||
// ... I write null as a string to the writer
|
||||
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(stream, 10, 10))
|
||||
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(stream, new QueryExecutionSettings()))
|
||||
{
|
||||
// Then:
|
||||
// ... I should get an argument null exception
|
||||
@@ -433,7 +488,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
|
||||
{
|
||||
// If:
|
||||
// ... I write null as a string to the writer
|
||||
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(stream, 10, 10))
|
||||
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(stream, new QueryExecutionSettings()))
|
||||
{
|
||||
// Then:
|
||||
// ... I should get an argument null exception
|
||||
|
||||
@@ -269,7 +269,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.SaveResults
|
||||
{
|
||||
Mock<IFileStreamFactory> mock = new Mock<IFileStreamFactory>();
|
||||
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
|
||||
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output])));
|
||||
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output]), new QueryExecutionSettings()));
|
||||
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
|
||||
.Returns<string>(output =>
|
||||
{
|
||||
@@ -284,7 +284,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.SaveResults
|
||||
{
|
||||
Mock<IFileStreamFactory> mock = new Mock<IFileStreamFactory>();
|
||||
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
|
||||
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output])));
|
||||
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output]), new QueryExecutionSettings()));
|
||||
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
|
||||
.Returns<string>(output =>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user