mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-15 02:48:35 -05:00
Save results to JSON file (#49)
* Save results to JSON file * Code cleanup * Code review changes * Changed comment
This commit is contained in:
@@ -18,16 +18,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
/// </summary>
|
||||
public string FilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The encoding of the file to save results in
|
||||
/// </summary>
|
||||
public string FileEncoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Include headers of columns in CSV
|
||||
/// </summary>
|
||||
public bool IncludeHeaders { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Index of the batch to get the results from
|
||||
/// </summary>
|
||||
@@ -38,15 +28,38 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
/// </summary>
|
||||
public int ResultSetIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// URI for the editor that called save results
|
||||
/// </summary>
|
||||
public string OwnerUri { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parameters to save results as CSV
|
||||
/// </summary>
|
||||
public class SaveResultsAsCsvRequestParams: SaveResultsRequestParams{
|
||||
|
||||
/// <summary>
|
||||
/// CSV - Write values in quotes
|
||||
/// </summary>
|
||||
public Boolean ValueInQuotes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// URI for the editor that called save results
|
||||
/// The encoding of the file to save results in
|
||||
/// </summary>
|
||||
public string OwnerUri { get; set; }
|
||||
public string FileEncoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Include headers of columns in CSV
|
||||
/// </summary>
|
||||
public bool IncludeHeaders { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parameters to save results as JSON
|
||||
/// </summary>
|
||||
public class SaveResultsAsJsonRequestParams: SaveResultsRequestParams{
|
||||
//TODO: define config for save as JSON
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -60,11 +73,24 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
public string Messages { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request type to save results as CSV
|
||||
/// </summary>
|
||||
public class SaveResultsAsCsvRequest
|
||||
{
|
||||
public static readonly
|
||||
RequestType<SaveResultsRequestParams, SaveResultRequestResult> Type =
|
||||
RequestType<SaveResultsRequestParams, SaveResultRequestResult>.Create("query/save");
|
||||
RequestType<SaveResultsAsCsvRequestParams, SaveResultRequestResult> Type =
|
||||
RequestType<SaveResultsAsCsvRequestParams, SaveResultRequestResult>.Create("query/saveCsv");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request type to save results as JSON
|
||||
/// </summary>
|
||||
public class SaveResultsAsJsonRequest
|
||||
{
|
||||
public static readonly
|
||||
RequestType<SaveResultsAsJsonRequestParams, SaveResultRequestResult> Type =
|
||||
RequestType<SaveResultsAsJsonRequestParams, SaveResultRequestResult>.Create("query/saveJson");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,6 +14,7 @@ using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
{
|
||||
@@ -100,6 +101,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
serviceHost.SetRequestHandler(QueryDisposeRequest.Type, HandleDisposeRequest);
|
||||
serviceHost.SetRequestHandler(QueryCancelRequest.Type, HandleCancelRequest);
|
||||
serviceHost.SetRequestHandler(SaveResultsAsCsvRequest.Type, HandleSaveResultsAsCsvRequest);
|
||||
serviceHost.SetRequestHandler(SaveResultsAsJsonRequest.Type, HandleSaveResultsAsJsonRequest);
|
||||
|
||||
// Register handler for shutdown event
|
||||
serviceHost.RegisterShutdownTask((shutdownParams, requestContext) =>
|
||||
@@ -261,7 +263,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <summary>
|
||||
/// Process request to save a resultSet to a file in CSV format
|
||||
/// </summary>
|
||||
public async Task HandleSaveResultsAsCsvRequest( SaveResultsRequestParams saveParams,
|
||||
public async Task HandleSaveResultsAsCsvRequest( SaveResultsAsCsvRequestParams saveParams,
|
||||
RequestContext<SaveResultRequestResult> requestContext)
|
||||
{
|
||||
// retrieve query for OwnerUri
|
||||
@@ -276,28 +278,94 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
try
|
||||
{
|
||||
using (StreamWriter csvFile = new StreamWriter(File.OpenWrite(saveParams.FilePath)))
|
||||
using (StreamWriter csvFile = new StreamWriter(File.Open(saveParams.FilePath, FileMode.Create)))
|
||||
{
|
||||
// get the requested resultSet from query
|
||||
Batch selectedBatch = result.Batches[saveParams.BatchIndex];
|
||||
ResultSet selectedResultSet = (selectedBatch.ResultSets.ToList())[saveParams.ResultSetIndex];
|
||||
if ( saveParams.IncludeHeaders)
|
||||
if (saveParams.IncludeHeaders)
|
||||
{
|
||||
// write column names to csv
|
||||
await csvFile.WriteLineAsync( string.Join( ",", selectedResultSet.Columns.Select( column => SaveResults.EncodeCsvField(column.ColumnName) ?? string.Empty)));
|
||||
}
|
||||
|
||||
// write rows to csv
|
||||
foreach( var row in selectedResultSet.Rows)
|
||||
foreach (var row in selectedResultSet.Rows)
|
||||
{
|
||||
await csvFile.WriteLineAsync(string.Join( ",", row.Select( field => SaveResults.EncodeCsvField( (field != null) ? field.ToString(): string.Empty))));
|
||||
await csvFile.WriteLineAsync( string.Join( ",", row.Select( field => SaveResults.EncodeCsvField((field != null) ? field.ToString(): string.Empty))));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
// Delete file when exception occurs
|
||||
if(File.Exists(saveParams.FilePath))
|
||||
if (File.Exists(saveParams.FilePath))
|
||||
{
|
||||
File.Delete(saveParams.FilePath);
|
||||
}
|
||||
await requestContext.SendError(ex.Message);
|
||||
return;
|
||||
}
|
||||
await requestContext.SendResult(new SaveResultRequestResult
|
||||
{
|
||||
Messages = "Success"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process request to save a resultSet to a file in JSON format
|
||||
/// </summary>
|
||||
public async Task HandleSaveResultsAsJsonRequest( SaveResultsAsJsonRequestParams saveParams,
|
||||
RequestContext<SaveResultRequestResult> requestContext)
|
||||
{
|
||||
// retrieve query for OwnerUri
|
||||
Query result;
|
||||
if (!ActiveQueries.TryGetValue(saveParams.OwnerUri, out result))
|
||||
{
|
||||
await requestContext.SendResult(new SaveResultRequestResult
|
||||
{
|
||||
Messages = "Failed to save results, ID not found."
|
||||
});
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
using (StreamWriter jsonFile = new StreamWriter(File.Open(saveParams.FilePath, FileMode.Create)))
|
||||
using (JsonWriter jsonWriter = new JsonTextWriter(jsonFile) )
|
||||
{
|
||||
jsonWriter.Formatting = Formatting.Indented;
|
||||
jsonWriter.WriteStartArray();
|
||||
|
||||
// get the requested resultSet from query
|
||||
Batch selectedBatch = result.Batches[saveParams.BatchIndex];
|
||||
ResultSet selectedResultSet = (selectedBatch.ResultSets.ToList())[saveParams.ResultSetIndex];
|
||||
|
||||
// write each row to JSON
|
||||
foreach (var row in selectedResultSet.Rows)
|
||||
{
|
||||
jsonWriter.WriteStartObject();
|
||||
foreach (var field in row.Select((value,i) => new {value, i}))
|
||||
{
|
||||
jsonWriter.WritePropertyName(selectedResultSet.Columns[field.i].ColumnName);
|
||||
if (field.value != null)
|
||||
{
|
||||
jsonWriter.WriteValue(field.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonWriter.WriteNull();
|
||||
}
|
||||
}
|
||||
jsonWriter.WriteEndObject();
|
||||
}
|
||||
jsonWriter.WriteEndArray();
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
// Delete file when exception occurs
|
||||
if (File.Exists(saveParams.FilePath))
|
||||
{
|
||||
File.Delete(saveParams.FilePath);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
||||
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||
|
||||
// Request to save the results as csv with correct parameters
|
||||
var saveParams = new SaveResultsRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 };
|
||||
var saveParams = new SaveResultsAsCsvRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 };
|
||||
saveParams.FilePath = "testwrite.csv";
|
||||
saveParams.IncludeHeaders = true;
|
||||
SaveResultRequestResult result = null;
|
||||
@@ -46,14 +46,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
||||
VerifySaveResultsCallCount(saveRequest, Times.Once(), Times.Never());
|
||||
|
||||
// Delete temp file after test
|
||||
if(File.Exists(saveParams.FilePath))
|
||||
if (File.Exists(saveParams.FilePath))
|
||||
{
|
||||
File.Delete(saveParams.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test handling exception in saving results to file
|
||||
/// Test handling exception in saving results to CSV file
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SaveResultsAsCsvExceptionTest()
|
||||
@@ -65,8 +65,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
||||
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||
|
||||
// Request to save the results as csv with incorrect filepath
|
||||
var saveParams = new SaveResultsRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 };
|
||||
if ( RuntimeInformation.IsOSPlatform( OSPlatform.Windows))
|
||||
var saveParams = new SaveResultsAsCsvRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 };
|
||||
if (RuntimeInformation.IsOSPlatform( OSPlatform.Windows))
|
||||
{
|
||||
saveParams.FilePath = "G:\\test.csv";
|
||||
}
|
||||
@@ -75,8 +75,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
||||
saveParams.FilePath = "/test.csv";
|
||||
}
|
||||
// SaveResultRequestResult result = null;
|
||||
String errMessage = null;
|
||||
var saveRequest = GetSaveResultsContextMock( null, err => errMessage = (String) err);
|
||||
string errMessage = null;
|
||||
var saveRequest = GetSaveResultsContextMock( null, err => errMessage = (string) err);
|
||||
queryService.ActiveQueries[Common.OwnerUri].Batches[0] = Common.GetBasicExecutedBatch();
|
||||
queryService.HandleSaveResultsAsCsvRequest(saveParams, saveRequest.Object).Wait();
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test saving results to file when the requested result set is no longer active
|
||||
/// Test saving results to CSV file when the requested result set is no longer active
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SaveResultsAsCsvQueryNotFoundTest()
|
||||
@@ -99,11 +99,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
||||
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||
|
||||
// Request to save the results as csv with query that is no longer active
|
||||
var saveParams = new SaveResultsRequestParams { OwnerUri = "falseuri", ResultSetIndex = 0, BatchIndex = 0 };
|
||||
var saveParams = new SaveResultsAsCsvRequestParams { OwnerUri = "falseuri", ResultSetIndex = 0, BatchIndex = 0 };
|
||||
saveParams.FilePath = "testwrite.csv";
|
||||
SaveResultRequestResult result = null;
|
||||
var saveRequest = GetSaveResultsContextMock(qcr => result = qcr, null);
|
||||
// queryService.ActiveQueries[Common.OwnerUri].Batches[0] = Common.GetBasicExecutedBatch();
|
||||
queryService.HandleSaveResultsAsCsvRequest(saveParams, saveRequest.Object).Wait();
|
||||
|
||||
// Expect message that save failed
|
||||
@@ -112,6 +111,97 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
||||
VerifySaveResultsCallCount(saveRequest, Times.Once(), Times.Never());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test save results to a file as JSON with correct parameters
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SaveResultsAsJsonSuccessTest()
|
||||
{
|
||||
// Execute a query
|
||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
||||
var executeParams = new QueryExecuteParams { QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri };
|
||||
var executeRequest = GetQueryExecuteResultContextMock(null, null, null);
|
||||
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||
|
||||
// Request to save the results as json with correct parameters
|
||||
var saveParams = new SaveResultsAsJsonRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 };
|
||||
saveParams.FilePath = "testwrite.json";
|
||||
SaveResultRequestResult result = null;
|
||||
var saveRequest = GetSaveResultsContextMock(qcr => result = qcr, null);
|
||||
queryService.ActiveQueries[Common.OwnerUri].Batches[0] = Common.GetBasicExecutedBatch();
|
||||
queryService.HandleSaveResultsAsJsonRequest(saveParams, saveRequest.Object).Wait();
|
||||
|
||||
// Expect to see a file successfully created in filepath and a success message
|
||||
Assert.Equal("Success", result.Messages);
|
||||
Assert.True(File.Exists(saveParams.FilePath));
|
||||
VerifySaveResultsCallCount(saveRequest, Times.Once(), Times.Never());
|
||||
|
||||
// Delete temp file after test
|
||||
if (File.Exists(saveParams.FilePath))
|
||||
{
|
||||
File.Delete(saveParams.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test handling exception in saving results to JSON file
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SaveResultsAsJsonExceptionTest()
|
||||
{
|
||||
// Execute a query
|
||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
||||
var executeParams = new QueryExecuteParams { QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri };
|
||||
var executeRequest = GetQueryExecuteResultContextMock(null, null, null);
|
||||
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||
|
||||
// Request to save the results as json with incorrect filepath
|
||||
var saveParams = new SaveResultsAsJsonRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 };
|
||||
if (RuntimeInformation.IsOSPlatform( OSPlatform.Windows))
|
||||
{
|
||||
saveParams.FilePath = "G:\\test.json";
|
||||
}
|
||||
else
|
||||
{
|
||||
saveParams.FilePath = "/test.json";
|
||||
}
|
||||
// SaveResultRequestResult result = null;
|
||||
string errMessage = null;
|
||||
var saveRequest = GetSaveResultsContextMock( null, err => errMessage = (string) err);
|
||||
queryService.ActiveQueries[Common.OwnerUri].Batches[0] = Common.GetBasicExecutedBatch();
|
||||
queryService.HandleSaveResultsAsJsonRequest(saveParams, saveRequest.Object).Wait();
|
||||
|
||||
// Expect to see error message
|
||||
Assert.NotNull(errMessage);
|
||||
VerifySaveResultsCallCount(saveRequest, Times.Never(), Times.Once());
|
||||
Assert.False(File.Exists(saveParams.FilePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test saving results to JSON file when the requested result set is no longer active
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SaveResultsAsJsonQueryNotFoundTest()
|
||||
{
|
||||
// Execute a query
|
||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
||||
var executeParams = new QueryExecuteParams { QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri };
|
||||
var executeRequest = GetQueryExecuteResultContextMock(null, null, null);
|
||||
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||
|
||||
// Request to save the results as json with query that is no longer active
|
||||
var saveParams = new SaveResultsAsJsonRequestParams { OwnerUri = "falseuri", ResultSetIndex = 0, BatchIndex = 0 };
|
||||
saveParams.FilePath = "testwrite.json";
|
||||
SaveResultRequestResult result = null;
|
||||
var saveRequest = GetSaveResultsContextMock(qcr => result = qcr, null);
|
||||
queryService.HandleSaveResultsAsJsonRequest(saveParams, saveRequest.Object).Wait();
|
||||
|
||||
// Expect message that save failed
|
||||
Assert.Equal("Failed to save results, ID not found.", result.Messages);
|
||||
Assert.False(File.Exists(saveParams.FilePath));
|
||||
VerifySaveResultsCallCount(saveRequest, Times.Once(), Times.Never());
|
||||
}
|
||||
|
||||
#region Mocking
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user