mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-17 01:25:40 -05:00
feature/edit/subset (#283)
* Changing query/subset API to only use Result on success, Error on error * Creating an interservice API for getting query result subsets * Updates to subset API * RowStartIndex is now long * Output of query/subset is a 2D array of DbCellValue * Adding LongSkip method to LongList to allow skipping ahead by longs * Moving LongList back to ServiceLayer utilities. Move refactoring * Stubbing out request for edit/subset * Initial implementation of getting edit rows * Unit tests for RowEdit and RowDelete .GetEditRow * Fixing major bugs in LongList implementation, adding much more thorough tests * Adding some more unit tests and fixes to make unit tests pass * Fixing comment
This commit is contained in:
@@ -355,7 +355,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <param name="startRow">The starting row of the results</param>
|
||||
/// <param name="rowCount">How many rows to retrieve</param>
|
||||
/// <returns>A subset of results</returns>
|
||||
public Task<ResultSetSubset> GetSubset(int resultSetIndex, int startRow, int rowCount)
|
||||
public Task<ResultSetSubset> GetSubset(int resultSetIndex, long startRow, int rowCount)
|
||||
{
|
||||
ResultSet targetResultSet;
|
||||
lock (resultSets)
|
||||
|
||||
@@ -19,6 +19,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
/// <summary>
|
||||
/// 2D array of the cell values requested from result set
|
||||
/// </summary>
|
||||
public string[][] Rows { get; set; }
|
||||
public DbCellValue[][] Rows { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
/// Beginning index of the rows to return from the selected resultset. This index will be
|
||||
/// included in the results.
|
||||
/// </summary>
|
||||
public int RowsStartIndex { get; set; }
|
||||
public long RowsStartIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of rows to include in the result of this request. If the number of the rows
|
||||
@@ -46,11 +46,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
/// </summary>
|
||||
public class SubsetResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Subset request error messages. Optional, can be set to null to indicate no errors
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The requested subset of results. Optional, can be set to null to indicate an error
|
||||
/// </summary>
|
||||
|
||||
@@ -280,7 +280,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <param name="startRow">The starting row of the results</param>
|
||||
/// <param name="rowCount">How many rows to retrieve</param>
|
||||
/// <returns>A subset of results</returns>
|
||||
public Task<ResultSetSubset> GetSubset(int batchIndex, int resultSetIndex, int startRow, int rowCount)
|
||||
public Task<ResultSetSubset> GetSubset(int batchIndex, int resultSetIndex, long startRow, int rowCount)
|
||||
{
|
||||
// Sanity check to make sure that the batch is within bounds
|
||||
if (batchIndex < 0 || batchIndex >= Batches.Length)
|
||||
|
||||
@@ -176,42 +176,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
{
|
||||
try
|
||||
{
|
||||
// Attempt to load the query
|
||||
Query query;
|
||||
if (!ActiveQueries.TryGetValue(subsetParams.OwnerUri, out query))
|
||||
{
|
||||
await requestContext.SendResult(new SubsetResult
|
||||
{
|
||||
Message = SR.QueryServiceRequestsNoQuery
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve the requested subset and return it
|
||||
ResultSetSubset subset = await InterServiceResultSubset(subsetParams);
|
||||
var result = new SubsetResult
|
||||
{
|
||||
Message = null,
|
||||
ResultSubset = await query.GetSubset(subsetParams.BatchIndex,
|
||||
subsetParams.ResultSetIndex, subsetParams.RowsStartIndex, subsetParams.RowsCount)
|
||||
ResultSubset = subset
|
||||
};
|
||||
await requestContext.SendResult(result);
|
||||
}
|
||||
catch (InvalidOperationException ioe)
|
||||
{
|
||||
// Return the error as a result
|
||||
await requestContext.SendResult(new SubsetResult
|
||||
{
|
||||
Message = ioe.Message
|
||||
});
|
||||
}
|
||||
catch (ArgumentOutOfRangeException aoore)
|
||||
{
|
||||
// Return the error as a result
|
||||
await requestContext.SendResult(new SubsetResult
|
||||
{
|
||||
Message = aoore.Message
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// This was unexpected, so send back as error
|
||||
@@ -415,7 +386,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <param name="ownerUri">The identifier of the query to be disposed</param>
|
||||
/// <param name="successAction">Action to perform on success</param>
|
||||
/// <param name="failureAction">Action to perform on failure</param>
|
||||
/// <returns></returns>
|
||||
public async Task InterServiceDisposeQuery(string ownerUri, Func<Task> successAction,
|
||||
Func<string, Task> failureAction)
|
||||
{
|
||||
@@ -444,6 +414,29 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the requested subset of rows from the requested result set. Intended to be
|
||||
/// called by another service.
|
||||
/// </summary>
|
||||
/// <param name="subsetParams">Parameters for the subset to retrieve</param>
|
||||
/// <returns>The requested subset</returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The requested query does not exist</exception>
|
||||
public async Task<ResultSetSubset> InterServiceResultSubset(SubsetParams subsetParams)
|
||||
{
|
||||
Validate.IsNotNullOrEmptyString(nameof(subsetParams.OwnerUri), subsetParams.OwnerUri);
|
||||
|
||||
// Attempt to load the query
|
||||
Query query;
|
||||
if (!ActiveQueries.TryGetValue(subsetParams.OwnerUri, out query))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(SR.QueryServiceRequestsNoQuery);
|
||||
}
|
||||
|
||||
// Retrieve the requested subset and return it
|
||||
return await query.GetSubset(subsetParams.BatchIndex, subsetParams.ResultSetIndex,
|
||||
subsetParams.RowsStartIndex, subsetParams.RowsCount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
@@ -223,7 +224,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <param name="startRow">The starting row of the results</param>
|
||||
/// <param name="rowCount">How many rows to retrieve</param>
|
||||
/// <returns>A subset of results</returns>
|
||||
public Task<ResultSetSubset> GetSubset(int startRow, int rowCount)
|
||||
public Task<ResultSetSubset> GetSubset(long startRow, int rowCount)
|
||||
{
|
||||
// Sanity check to make sure that the results have been read beforehand
|
||||
if (!hasBeenRead)
|
||||
@@ -244,7 +245,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
return Task.Factory.StartNew(() =>
|
||||
{
|
||||
|
||||
string[][] rows;
|
||||
DbCellValue[][] rows;
|
||||
|
||||
using (IFileStreamReader fileStreamReader = fileStreamFactory.GetReader(outputFileName))
|
||||
{
|
||||
@@ -255,19 +256,23 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
// Iterate over all the rows and process them into a list of string builders
|
||||
// ReSharper disable once AccessToDisposedClosure The lambda is used immediately in string.Join call
|
||||
IEnumerable<string> rowValues = fileOffsets.Select(rowOffset => fileStreamReader.ReadRow(rowOffset, Columns)[0].DisplayValue);
|
||||
rows = new[] { new[] { string.Join(string.Empty, rowValues) } };
|
||||
string singleString = string.Join(string.Empty, rowValues);
|
||||
DbCellValue cellValue = new DbCellValue
|
||||
{
|
||||
DisplayValue = singleString,
|
||||
IsNull = false,
|
||||
RawObject = singleString
|
||||
};
|
||||
rows = new[] { new[] { cellValue } };
|
||||
}
|
||||
else
|
||||
{
|
||||
// Figure out which rows we need to read back
|
||||
IEnumerable<long> rowOffsets = fileOffsets.Skip(startRow).Take(rowCount);
|
||||
IEnumerable<long> rowOffsets = fileOffsets.LongSkip(startRow).Take(rowCount);
|
||||
|
||||
// Iterate over the rows we need and process them into output
|
||||
// ReSharper disable once AccessToDisposedClosure The lambda is used immediately in .ToArray call
|
||||
rows = rowOffsets.Select(rowOffset => fileStreamReader.ReadRow(rowOffset, Columns)
|
||||
.Select(cell => cell.DisplayValue).ToArray())
|
||||
.ToArray();
|
||||
|
||||
rows = rowOffsets.Select(rowOffset => fileStreamReader.ReadRow(rowOffset, Columns).ToArray()).ToArray();
|
||||
}
|
||||
}
|
||||
// Retrieve the subset of the results as per the request
|
||||
|
||||
Reference in New Issue
Block a user