mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Feature/save selection (#64)
* Save selection * Add tests * Change filename in test * Code cleanup * Refactor handler * Code cleanup * Modify tests to have query selection * Change variable declaration
This commit is contained in:
@@ -32,6 +32,28 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
|||||||
/// URI for the editor that called save results
|
/// URI for the editor that called save results
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OwnerUri { get; set; }
|
public string OwnerUri { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start index of the selected rows (inclusive)
|
||||||
|
/// </summary>
|
||||||
|
public int? RowStartIndex { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// End index of the selected rows (inclusive)
|
||||||
|
/// </summary>
|
||||||
|
public int? RowEndIndex { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start index of the selected columns (inclusive)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int? ColumnStartIndex { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// End index of the selected columns (inclusive)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int? ColumnEndIndex { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -287,20 +287,41 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
|||||||
{
|
{
|
||||||
// get the requested resultSet from query
|
// get the requested resultSet from query
|
||||||
Batch selectedBatch = result.Batches[saveParams.BatchIndex];
|
Batch selectedBatch = result.Batches[saveParams.BatchIndex];
|
||||||
ResultSet selectedResultSet = selectedBatch.ResultSets.ToList()[saveParams.ResultSetIndex];
|
ResultSet selectedResultSet = (selectedBatch.ResultSets.ToList())[saveParams.ResultSetIndex];
|
||||||
if (saveParams.IncludeHeaders)
|
int columnCount = 0;
|
||||||
|
int rowCount = 0;
|
||||||
|
int columnStartIndex = 0;
|
||||||
|
int rowStartIndex = 0;
|
||||||
|
|
||||||
|
// set column, row counts depending on whether save request is for entire result set or a subset
|
||||||
|
if (SaveResults.isSaveSelection(saveParams))
|
||||||
{
|
{
|
||||||
// write column names to csv
|
columnCount = saveParams.ColumnEndIndex.Value - saveParams.ColumnStartIndex.Value + 1;
|
||||||
await csvFile.WriteLineAsync(string.Join(",",
|
rowCount = saveParams.RowEndIndex.Value - saveParams.RowStartIndex.Value + 1;
|
||||||
selectedResultSet.Columns.Select(column => SaveResults.EncodeCsvField(column.ColumnName) ?? string.Empty)));
|
columnStartIndex = saveParams.ColumnStartIndex.Value;
|
||||||
|
rowStartIndex =saveParams.RowStartIndex.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
columnCount = selectedResultSet.Columns.Length;
|
||||||
|
rowCount = (int)selectedResultSet.RowCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write rows to csv
|
// write column names if include headers option is chosen
|
||||||
foreach (var row in selectedResultSet.Rows)
|
if (saveParams.IncludeHeaders)
|
||||||
{
|
{
|
||||||
await csvFile.WriteLineAsync(string.Join(",",
|
await csvFile.WriteLineAsync( string.Join( ",", selectedResultSet.Columns.Skip(columnStartIndex).Take(columnCount).Select( column =>
|
||||||
row.Select(field => SaveResults.EncodeCsvField(field ?? string.Empty))));
|
SaveResults.EncodeCsvField(column.ColumnName) ?? string.Empty)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// retrieve rows and write as csv
|
||||||
|
ResultSetSubset resultSubset = await result.GetSubset(saveParams.BatchIndex, saveParams.ResultSetIndex, rowStartIndex, rowCount);
|
||||||
|
foreach (var row in resultSubset.Rows)
|
||||||
|
{
|
||||||
|
await csvFile.WriteLineAsync( string.Join( ",", row.Skip(columnStartIndex).Take(columnCount).Select( field =>
|
||||||
|
SaveResults.EncodeCsvField((field != null) ? field.ToString(): "NULL"))));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Successfully wrote file, send success result
|
// Successfully wrote file, send success result
|
||||||
@@ -344,16 +365,36 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
|||||||
// get the requested resultSet from query
|
// get the requested resultSet from query
|
||||||
Batch selectedBatch = result.Batches[saveParams.BatchIndex];
|
Batch selectedBatch = result.Batches[saveParams.BatchIndex];
|
||||||
ResultSet selectedResultSet = selectedBatch.ResultSets.ToList()[saveParams.ResultSetIndex];
|
ResultSet selectedResultSet = selectedBatch.ResultSets.ToList()[saveParams.ResultSetIndex];
|
||||||
|
int rowCount = 0;
|
||||||
|
int rowStartIndex = 0;
|
||||||
|
int columnStartIndex = 0;
|
||||||
|
int columnEndIndex = 0;
|
||||||
|
|
||||||
// write each row to JSON
|
// set column, row counts depending on whether save request is for entire result set or a subset
|
||||||
foreach (var row in selectedResultSet.Rows)
|
if (SaveResults.isSaveSelection(saveParams))
|
||||||
|
{
|
||||||
|
|
||||||
|
rowCount = saveParams.RowEndIndex.Value - saveParams.RowStartIndex.Value + 1;
|
||||||
|
rowStartIndex = saveParams.RowStartIndex.Value;
|
||||||
|
columnStartIndex = saveParams.ColumnStartIndex.Value;
|
||||||
|
columnEndIndex = saveParams.ColumnEndIndex.Value + 1 ; // include the last column
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rowCount = (int)selectedResultSet.RowCount;
|
||||||
|
columnEndIndex = selectedResultSet.Columns.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve rows and write as json
|
||||||
|
ResultSetSubset resultSubset = await result.GetSubset(saveParams.BatchIndex, saveParams.ResultSetIndex, rowStartIndex, rowCount);
|
||||||
|
foreach (var row in resultSubset.Rows)
|
||||||
{
|
{
|
||||||
jsonWriter.WriteStartObject();
|
jsonWriter.WriteStartObject();
|
||||||
for (int i = 0; i < row.Length; i++)
|
for (int i = columnStartIndex ; i < columnEndIndex; i++)
|
||||||
{
|
{
|
||||||
|
//get column name
|
||||||
DbColumnWrapper col = selectedResultSet.Columns[i];
|
DbColumnWrapper col = selectedResultSet.Columns[i];
|
||||||
string val = row[i];
|
string val = row[i]?.ToString();
|
||||||
|
|
||||||
jsonWriter.WritePropertyName(col.ColumnName);
|
jsonWriter.WritePropertyName(col.ColumnName);
|
||||||
if (val == null)
|
if (val == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
//
|
//
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||||
{
|
{
|
||||||
@@ -79,6 +80,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool isSaveSelection(SaveResultsRequestParams saveParams)
|
||||||
|
{
|
||||||
|
return (saveParams.ColumnStartIndex != null && saveParams.ColumnEndIndex != null
|
||||||
|
&& saveParams.RowEndIndex != null && saveParams.RowEndIndex != null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -68,6 +68,57 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test save results to a file as CSV with a selection of cells and correct parameters
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void SaveResultsAsCsvWithSelectionSuccessTest()
|
||||||
|
{
|
||||||
|
|
||||||
|
// Set up file for returning the query
|
||||||
|
var fileMock = new Mock<ScriptFile>();
|
||||||
|
fileMock.SetupGet(file => file.Contents).Returns(Common.StandardQuery);
|
||||||
|
// Set up workspace mock
|
||||||
|
var workspaceService = new Mock<WorkspaceService<SqlToolsSettings>>();
|
||||||
|
workspaceService.Setup(service => service.Workspace.GetFile(It.IsAny<string>()))
|
||||||
|
.Returns(fileMock.Object);
|
||||||
|
|
||||||
|
// Execute a query
|
||||||
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true, workspaceService.Object);
|
||||||
|
var executeParams = new QueryExecuteParams { QuerySelection = Common.WholeDocument , OwnerUri = Common.OwnerUri };
|
||||||
|
var executeRequest = GetQueryExecuteResultContextMock(null, null, null);
|
||||||
|
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||||
|
|
||||||
|
// Request to save the results as csv with correct parameters
|
||||||
|
var saveParams = new SaveResultsAsCsvRequestParams
|
||||||
|
{
|
||||||
|
OwnerUri = Common.OwnerUri,
|
||||||
|
ResultSetIndex = 0,
|
||||||
|
BatchIndex = 0,
|
||||||
|
FilePath = "testwrite_2.csv",
|
||||||
|
IncludeHeaders = true,
|
||||||
|
RowStartIndex = 0,
|
||||||
|
RowEndIndex = 0,
|
||||||
|
ColumnStartIndex = 0,
|
||||||
|
ColumnEndIndex = 0
|
||||||
|
};
|
||||||
|
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 to see a file successfully created in filepath and a success message
|
||||||
|
Assert.Null(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>
|
/// <summary>
|
||||||
/// Test handling exception in saving results to CSV file
|
/// Test handling exception in saving results to CSV file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -186,6 +237,55 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test save results to a file as JSON with a selection of cells and correct parameters
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void SaveResultsAsJsonWithSelectionSuccessTest()
|
||||||
|
{
|
||||||
|
// Set up file for returning the query
|
||||||
|
var fileMock = new Mock<ScriptFile>();
|
||||||
|
fileMock.SetupGet(file => file.Contents).Returns(Common.StandardQuery);
|
||||||
|
// Set up workspace mock
|
||||||
|
var workspaceService = new Mock<WorkspaceService<SqlToolsSettings>>();
|
||||||
|
workspaceService.Setup(service => service.Workspace.GetFile(It.IsAny<string>()))
|
||||||
|
.Returns(fileMock.Object);
|
||||||
|
|
||||||
|
// Execute a query
|
||||||
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true, workspaceService.Object);
|
||||||
|
var executeParams = new QueryExecuteParams { QuerySelection = Common.WholeDocument , 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,
|
||||||
|
FilePath = "testwrite_5.json",
|
||||||
|
RowStartIndex = 0,
|
||||||
|
RowEndIndex = 0,
|
||||||
|
ColumnStartIndex = 0,
|
||||||
|
ColumnEndIndex = 0
|
||||||
|
};
|
||||||
|
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.Null(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>
|
/// <summary>
|
||||||
/// Test handling exception in saving results to JSON file
|
/// Test handling exception in saving results to JSON file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user