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:
Benjamin Russell
2017-02-21 19:29:55 -08:00
committed by GitHub
parent ccd2c9caa9
commit 55a56be316
14 changed files with 199 additions and 113 deletions

View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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
{

View File

@@ -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));
}

View File

@@ -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 =>

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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 =>
{