mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-18 01:25:41 -05:00
Progressive Results Part 2: Result Completion Event (#134)
The main change in this pull request is to add a new event that will be fired upon completion of a resultset but before the completion of a batch. This event will only fire if a resultset is available and generated. Changes: * ConnectionService - Slight changes to enable mocking, cleanup * Batch - Moving summary generation into ResultSet class, adding generation of ordinals for resultset and locking of result set list (which needs further refinement, but would be outside scope of this change) * Adding new event and associated parameters for completion of a resultset. Params return the resultset summary * Adding logic for assigning the event a handler in the query execution service * Adding unit tests for testing the new event /making sure the existing tests work * Refactoring some private properties into member variables * Refactor to remove SectionData class in favor of BufferRange * Adding callback for batch completion that will let the extension know that a batch has completed execution * Refactoring to make progressive results work as per async query execution * Allowing retrieval of batch results while query is in progress * reverting global.json, whoops * Adding a few missing comments, and fixing a couple code style bugs * Using SelectionData everywhere again * One more missing comment * Adding new notification type for result set completion * Plumbing event for result set completion * Unit tests for result set events This includes a fairly substantial change to create a mock of the ConnectionService and to create separate memorystream storage arrays. It preserves more correct behavior with a integration test, fixes an issue where the test db reader will return n-1 rows because the Reliable Connection Helper steals a record. * Adding locking to ResultSets for thread safety * Adding/fixing unit tests * Adding batch ID to result set summary
This commit is contained in:
@@ -88,6 +88,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// </summary>
|
||||
public event BatchAsyncEventHandler BatchCompletion;
|
||||
|
||||
/// <summary>
|
||||
/// Event that will be called when the resultset has completed execution. It will not be
|
||||
/// called from the Batch but from the ResultSet instance
|
||||
/// </summary>
|
||||
public event ResultSet.ResultSetAsyncEventHandler ResultSetCompletion;
|
||||
|
||||
/// <summary>
|
||||
/// The text of batch that will be executed
|
||||
/// </summary>
|
||||
@@ -155,12 +161,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
{
|
||||
get
|
||||
{
|
||||
return ResultSets.Select((set, index) => new ResultSetSummary()
|
||||
lock (resultSets)
|
||||
{
|
||||
ColumnInfo = set.Columns,
|
||||
Id = index,
|
||||
RowCount = set.RowCount
|
||||
}).ToArray();
|
||||
return resultSets.Select(set => set.Summary).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +225,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
command = sqlConn.GetUnderlyingConnection().CreateCommand();
|
||||
|
||||
// Add a handler for when the command completes
|
||||
SqlCommand sqlCommand = (SqlCommand) command;
|
||||
SqlCommand sqlCommand = (SqlCommand)command;
|
||||
sqlCommand.StatementCompleted += StatementCompletedHandler;
|
||||
}
|
||||
else
|
||||
@@ -244,6 +248,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
// Execute the command to get back a reader
|
||||
using (DbDataReader reader = await command.ExecuteReaderAsync(cancellationToken))
|
||||
{
|
||||
int resultSetOrdinal = 0;
|
||||
do
|
||||
{
|
||||
// Skip this result set if there aren't any rows (ie, UPDATE/DELETE/etc queries)
|
||||
@@ -253,11 +258,16 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
|
||||
// This resultset has results (ie, SELECT/etc queries)
|
||||
ResultSet resultSet = new ResultSet(reader, outputFileFactory);
|
||||
|
||||
ResultSet resultSet = new ResultSet(reader, resultSetOrdinal, Id, outputFileFactory);
|
||||
resultSet.ResultCompletion += ResultSetCompletion;
|
||||
|
||||
// Add the result set to the results of the query
|
||||
resultSets.Add(resultSet);
|
||||
|
||||
lock (resultSets)
|
||||
{
|
||||
resultSets.Add(resultSet);
|
||||
resultSetOrdinal++;
|
||||
}
|
||||
|
||||
// Read until we hit the end of the result set
|
||||
await resultSet.ReadResultToEnd(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -318,20 +328,21 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <returns>A subset of results</returns>
|
||||
public Task<ResultSetSubset> GetSubset(int resultSetIndex, int startRow, int rowCount)
|
||||
{
|
||||
// Sanity check to make sure that the batch has finished
|
||||
if (!HasExecuted)
|
||||
ResultSet targetResultSet;
|
||||
lock (resultSets)
|
||||
{
|
||||
throw new InvalidOperationException(SR.QueryServiceSubsetBatchNotCompleted);
|
||||
}
|
||||
// Sanity check to make sure we have valid numbers
|
||||
if (resultSetIndex < 0 || resultSetIndex >= resultSets.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(resultSetIndex),
|
||||
SR.QueryServiceSubsetResultSetOutOfRange);
|
||||
}
|
||||
|
||||
// Sanity check to make sure we have valid numbers
|
||||
if (resultSetIndex < 0 || resultSetIndex >= resultSets.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(resultSetIndex), SR.QueryServiceSubsetResultSetOutOfRange);
|
||||
targetResultSet = resultSets[resultSetIndex];
|
||||
}
|
||||
|
||||
// Retrieve the result set
|
||||
return resultSets[resultSetIndex].GetSubset(startRow, rowCount);
|
||||
return targetResultSet.GetSubset(startRow, rowCount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -431,9 +442,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
foreach (ResultSet r in ResultSets)
|
||||
lock (resultSets)
|
||||
{
|
||||
r.Dispose();
|
||||
foreach (ResultSet r in resultSets)
|
||||
{
|
||||
r.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user