Export headers in an empty result set (#1434)

* Minimal changes to make headers appear on empty result sets

* Columns for everyone!

* Updating tests - some don't pass yet

* Adding some more tests to verify the changes for column/row selection

* null default columns

* Updates to comments as per PR comments
This commit is contained in:
Benjamin Russell
2022-03-31 11:10:32 -05:00
committed by GitHub
parent 5d805bd678
commit 2ace786d95
24 changed files with 814 additions and 499 deletions

View File

@@ -27,7 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
// If: I attempt to save with a null set of params
// Then: I should get a null argument exception
ResultSet rs = new ResultSet(
Common.Ordinal, Common.Ordinal,
Common.Ordinal, Common.Ordinal,
MemoryFileSystem.GetFileStreamFactory());
Assert.Throws<ArgumentNullException>(() => rs.SaveAs(
null,
@@ -41,7 +41,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
// If: I attempt to save with a null set of params
// Then: I should get a null argument exception
ResultSet rs = new ResultSet(
Common.Ordinal, Common.Ordinal,
Common.Ordinal, Common.Ordinal,
MemoryFileSystem.GetFileStreamFactory());
Assert.Throws<ArgumentNullException>(() => rs.SaveAs(
new SaveResultsRequestParams(),
@@ -54,11 +54,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
// If: I attempt to save a result set that hasn't completed execution
// Then: I should get an invalid operation exception
ResultSet rs = new ResultSet(
Common.Ordinal, Common.Ordinal,
Common.Ordinal, Common.Ordinal,
MemoryFileSystem.GetFileStreamFactory());
Assert.Throws<InvalidOperationException>(() => rs.SaveAs(
new SaveResultsRequestParams(),
MemoryFileSystem.GetFileStreamFactory(),
new SaveResultsRequestParams(),
MemoryFileSystem.GetFileStreamFactory(),
null, null));
}
@@ -78,7 +78,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
// Then: I should get an invalid operation exception
var requestParams = new SaveResultsRequestParams {FilePath = Constants.OwnerUri};
Assert.Throws<InvalidOperationException>(() => rs.SaveAs(
requestParams, GetMockFactory(GetMockWriter().Object, null),
requestParams, GetMockFactory(GetMockWriter().Object, null),
null, null));
}
@@ -110,7 +110,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
// ... All the rows should have been written successfully
saveWriter.Verify(
w => w.WriteRow(It.IsAny<IList<DbCellValue>>(), It.IsAny<IList<DbColumnWrapper>>()),
w => w.WriteRow(It.IsAny<IList<DbCellValue>>(), It.IsAny<IReadOnlyList<DbColumnWrapper>>()),
Times.Exactly(Common.StandardRows));
}
@@ -150,21 +150,21 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
// ... All the rows should have been written successfully
saveWriter.Verify(
w => w.WriteRow(It.IsAny<IList<DbCellValue>>(), It.IsAny<IList<DbColumnWrapper>>()),
w => w.WriteRow(It.IsAny<IList<DbCellValue>>(), It.IsAny<IReadOnlyList<DbColumnWrapper>>()),
Times.Exactly((int) (saveParams.RowEndIndex - saveParams.RowStartIndex + 1)));
}
private static Mock<IFileStreamWriter> GetMockWriter()
{
var mockWriter = new Mock<IFileStreamWriter>();
mockWriter.Setup(w => w.WriteRow(It.IsAny<IList<DbCellValue>>(), It.IsAny<IList<DbColumnWrapper>>()));
mockWriter.Setup(w => w.WriteRow(It.IsAny<IList<DbCellValue>>(), It.IsAny<IReadOnlyList<DbColumnWrapper>>()));
return mockWriter;
}
private static IFileStreamFactory GetMockFactory(IFileStreamWriter writer, Func<string, IFileStreamReader> readerGenerator)
{
var mockFactory = new Mock<IFileStreamFactory>();
mockFactory.Setup(f => f.GetWriter(It.IsAny<string>()))
mockFactory.Setup(f => f.GetWriter(It.IsAny<string>(), It.IsAny<IReadOnlyList<DbColumnWrapper>>()))
.Returns(writer);
mockFactory.Setup(f => f.GetReader(It.IsAny<string>()))
.Returns(readerGenerator);

View File

@@ -1,4 +1,4 @@
//
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
@@ -50,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
[Test]
public async Task SaveResultAsCsvFailure()
{
// Given:
// Given:
// ... A working query and workspace service
WorkspaceService<SqlToolsSettings> ws = Common.GetPrimedWorkspaceService(Constants.StandardQuery);
ConcurrentDictionary<string, byte[]> storage;
@@ -96,7 +96,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
[Test]
public async Task SaveResultsAsCsvSuccess()
{
// Given:
// Given:
// ... A working query and workspace service
WorkspaceService<SqlToolsSettings> ws = Common.GetPrimedWorkspaceService(Constants.StandardQuery);
ConcurrentDictionary<string, byte[]> storage;
@@ -164,7 +164,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
[Test]
public async Task SaveResultAsJsonFailure()
{
// Given:
// Given:
// ... A working query and workspace service
WorkspaceService<SqlToolsSettings> ws = Common.GetPrimedWorkspaceService(Constants.StandardQuery);
ConcurrentDictionary<string, byte[]> storage;
@@ -208,7 +208,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
[Test]
public async Task SaveResultsAsJsonSuccess()
{
// Given:
// Given:
// ... A working query and workspace service
WorkspaceService<SqlToolsSettings> ws = Common.GetPrimedWorkspaceService(Constants.StandardQuery);
ConcurrentDictionary<string, byte[]> storage;
@@ -246,7 +246,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
}
#endregion
#region XML tests
[Test]
@@ -275,7 +275,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
[Test]
public async Task SaveResultAsXmlFailure()
{
// Given:
// Given:
// ... A working query and workspace service
WorkspaceService<SqlToolsSettings> ws = Common.GetPrimedWorkspaceService(Constants.StandardQuery);
ConcurrentDictionary<string, byte[]> storage;
@@ -319,7 +319,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
[Test]
public async Task SaveResultsAsXmlSuccess()
{
// Given:
// Given:
// ... A working query and workspace service
WorkspaceService<SqlToolsSettings> ws = Common.GetPrimedWorkspaceService(Constants.StandardQuery);
ConcurrentDictionary<string, byte[]> storage;
@@ -342,7 +342,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
Formatted = true
};
qes.XmlFileFactory = GetXmlStreamFactory(storage, saveParams);
var efv = new EventFlowValidator<SaveResultRequestResult>()
.AddStandardResultValidator()
.Complete();
@@ -359,9 +359,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
}
#endregion
#region Excel Tests
#region Excel Tests
[Test]
public async Task SaveResultsExcelNonExistentQuery()
{
@@ -388,7 +388,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
[Test]
public async Task SaveResultAsExcelFailure()
{
// Given:
// Given:
// ... A working query and workspace service
WorkspaceService<SqlToolsSettings> ws = Common.GetPrimedWorkspaceService(Constants.StandardQuery);
ConcurrentDictionary<string, byte[]> storage;
@@ -432,7 +432,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
[Test]
public async Task SaveResultsAsExcelSuccess()
{
// Given:
// Given:
// ... A working query and workspace service
WorkspaceService<SqlToolsSettings> ws = Common.GetPrimedWorkspaceService(Constants.StandardQuery);
ConcurrentDictionary<string, byte[]> storage;
@@ -468,70 +468,76 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
// ... There should not have been an error
efv.Validate();
}
#endregion
#region Private Helpers
private static IFileStreamFactory GetCsvStreamFactory(IDictionary<string, byte[]> storage, SaveResultsAsCsvRequestParams saveParams)
private static IFileStreamFactory GetCsvStreamFactory(
IDictionary<string, byte[]> storage,
SaveResultsAsCsvRequestParams saveParams)
{
Mock<IFileStreamFactory> mock = new Mock<IFileStreamFactory>();
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output]), new QueryExecutionSettings()));
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
.Returns<string>(output =>
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>(), It.IsAny<IReadOnlyList<DbColumnWrapper>>()))
.Returns<string, IReadOnlyList<DbColumnWrapper>>((output, columns) =>
{
storage.Add(output, new byte[8192]);
return new SaveAsCsvFileStreamWriter(new MemoryStream(storage[output]), saveParams);
return new SaveAsCsvFileStreamWriter(new MemoryStream(storage[output]), saveParams, columns);
});
return mock.Object;
}
private static IFileStreamFactory GetJsonStreamFactory(IDictionary<string, byte[]> storage, SaveResultsAsJsonRequestParams saveParams)
private static IFileStreamFactory GetJsonStreamFactory(
IDictionary<string, byte[]> storage,
SaveResultsAsJsonRequestParams saveParams)
{
Mock<IFileStreamFactory> mock = new Mock<IFileStreamFactory>();
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output]), new QueryExecutionSettings()));
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
.Returns<string>(output =>
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>(), It.IsAny<IReadOnlyList<DbColumnWrapper>>()))
.Returns<string, IReadOnlyList<DbColumnWrapper>>((output, columns) =>
{
storage.Add(output, new byte[8192]);
return new SaveAsJsonFileStreamWriter(new MemoryStream(storage[output]), saveParams);
return new SaveAsJsonFileStreamWriter(new MemoryStream(storage[output]), saveParams, columns);
});
return mock.Object;
}
private static IFileStreamFactory GetXmlStreamFactory(IDictionary<string, byte[]> storage,
private static IFileStreamFactory GetXmlStreamFactory(
IDictionary<string, byte[]> storage,
SaveResultsAsXmlRequestParams saveParams)
{
Mock<IFileStreamFactory> mock = new Mock<IFileStreamFactory>();
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output]), new QueryExecutionSettings()));
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
.Returns<string>(output =>
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>(), It.IsAny<IReadOnlyList<DbColumnWrapper>>()))
.Returns<string, IReadOnlyList<DbColumnWrapper>>((output, columns) =>
{
storage.Add(output, new byte[8192]);
return new SaveAsXmlFileStreamWriter(new MemoryStream(storage[output]), saveParams);
return new SaveAsXmlFileStreamWriter(new MemoryStream(storage[output]), saveParams, columns);
});
return mock.Object;
}
private static IFileStreamFactory GetExcelStreamFactory(IDictionary<string, byte[]> storage,
private static IFileStreamFactory GetExcelStreamFactory(
IDictionary<string, byte[]> storage,
SaveResultsAsExcelRequestParams saveParams)
{
Mock<IFileStreamFactory> mock = new Mock<IFileStreamFactory>();
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output]), new QueryExecutionSettings()));
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
.Returns<string>(output =>
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>(), It.IsAny<IReadOnlyList<DbColumnWrapper>>()))
.Returns<string, IReadOnlyList<DbColumnWrapper>>((output, columns) =>
{
storage.Add(output, new byte[8192]);
return new SaveAsExcelFileStreamWriter(new MemoryStream(storage[output]), saveParams);
return new SaveAsExcelFileStreamWriter(new MemoryStream(storage[output]), saveParams, columns);
});
return mock.Object;
}