Edit Data: Better errors for possible truncation (#514)

* Fix to make sql exceptions surface properly to user (with important notes!)

* Adding support for detecting column size issues when updating a cell

* Adding unit tests for the exception on read scenario
This commit is contained in:
Benjamin Russell
2017-10-21 11:08:40 -07:00
committed by Karl Burtram
parent 9499d73cec
commit e9bc97e290
37 changed files with 445 additions and 343 deletions

View File

@@ -71,7 +71,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
b => batchEndCalls++,
m => messages.Add(m),
r => resultSetCalls++);
await batch.Execute(GetConnection(Common.CreateTestConnectionInfo(null, false)), CancellationToken.None);
await batch.Execute(GetConnection(Common.CreateTestConnectionInfo(null, false, false)), CancellationToken.None);
// Then:
// ... Callbacks should have been called the appropriate number of times
@@ -97,7 +97,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// ... Build a data set to return
const int resultSets = 1;
ConnectionInfo ci = Common.CreateTestConnectionInfo(Common.GetTestDataSet(resultSets), false);
ConnectionInfo ci = Common.CreateTestConnectionInfo(Common.GetTestDataSet(resultSets), false, false);
// If I execute a query that should get one result set
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
@@ -133,7 +133,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// ... Build a data set to return
const int resultSets = 2;
ConnectionInfo ci = Common.CreateTestConnectionInfo(Common.GetTestDataSet(resultSets), false);
ConnectionInfo ci = Common.CreateTestConnectionInfo(Common.GetTestDataSet(resultSets), false, false);
// If I execute a query that should get two result sets
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
@@ -167,7 +167,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
List<ResultMessage> messages = new List<ResultMessage>();
// If I execute a batch that is invalid
var ci = Common.CreateTestConnectionInfo(null, true);
var ci = Common.CreateTestConnectionInfo(null, true, false);
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
Batch batch = new Batch(Constants.StandardQuery, Common.SubsectionDocument, Common.Ordinal, fileStreamFactory);
BatchCallbackHelper(batch,
@@ -200,7 +200,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
{
// Setup: Build a data set to return
const int resultSets = 1;
ConnectionInfo ci = Common.CreateTestConnectionInfo(Common.GetTestDataSet(resultSets), false);
ConnectionInfo ci = Common.CreateTestConnectionInfo(Common.GetTestDataSet(resultSets), false, false);
// If I execute a batch
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();

View File

@@ -24,7 +24,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
{
// If:
// ... I create a query
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false);
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false, false);
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
Query query = new Query(Constants.StandardQuery, ci, new QueryExecutionSettings(), fileStreamFactory);
@@ -53,7 +53,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// Then:
// ... It should throw an exception
Assert.Throws<ArgumentNullException>(() =>
new Query("Some query", Common.CreateTestConnectionInfo(null, false), null, MemoryFileSystem.GetFileStreamFactory()));
new Query("Some query", Common.CreateTestConnectionInfo(null, false, false), null, MemoryFileSystem.GetFileStreamFactory()));
}
[Fact]
@@ -64,7 +64,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// Then:
// ... It should throw an exception
Assert.Throws<ArgumentNullException>(() =>
new Query("Some query", Common.CreateTestConnectionInfo(null, false), new QueryExecutionSettings(), null));
new Query("Some query", Common.CreateTestConnectionInfo(null, false, false), new QueryExecutionSettings(), null));
}
[Fact]
@@ -78,7 +78,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I create a query from a single batch (without separator)
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false);
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false, false);
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
Query query = new Query(Constants.StandardQuery, ci, new QueryExecutionSettings(), fileStreamFactory);
BatchCallbackHelper(query,
@@ -114,7 +114,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I create a query from a single batch that does nothing
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false);
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false, false);
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
Query query = new Query(Common.NoOpQuery, ci, new QueryExecutionSettings(), fileStreamFactory);
BatchCallbackHelper(query,
@@ -149,7 +149,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I create a query from two batches (with separator)
ConnectionInfo ci = Common.CreateConnectedConnectionInfo(null, false);
ConnectionInfo ci = Common.CreateConnectedConnectionInfo(null, false, false);
string queryText = string.Format("{0}\r\nGO\r\n{0}", Constants.StandardQuery);
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
@@ -190,7 +190,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I create a query from a two batches (with separator)
ConnectionInfo ci = Common.CreateConnectedConnectionInfo(null, false);
ConnectionInfo ci = Common.CreateConnectedConnectionInfo(null, false, false);
string queryText = string.Format("{0}\r\nGO\r\n{1}", Constants.StandardQuery, Common.NoOpQuery);
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
Query query = new Query(queryText, ci, new QueryExecutionSettings(), fileStreamFactory);
@@ -226,7 +226,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I create a query from a two batches (with separator)
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false);
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false, false);
string queryText = string.Format("{0}\r\nGO\r\n{1}", Common.NoOpQuery, Common.NoOpQuery);
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();
Query query = new Query(queryText, ci, new QueryExecutionSettings(), fileStreamFactory);
@@ -261,7 +261,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I create a query from an invalid batch
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, true);
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, true, false);
ConnectionService.Instance.OwnerToConnectionMap[ci.OwnerUri] = ci;
var fileStreamFactory = MemoryFileSystem.GetFileStreamFactory();

View File

@@ -285,6 +285,28 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
Assert.Equal(Common.StandardRows, resultSet.RowCount);
}
[Fact]
public async Task AddRowThrowsOnRead()
{
// Setup:
// ... Create a standard result set with standard data
var fileFactory = MemoryFileSystem.GetFileStreamFactory();
var mockReader = GetReader(Common.StandardTestDataSet, false, Constants.StandardQuery);
ResultSet resultSet = new ResultSet(Common.Ordinal, Common.Ordinal, fileFactory);
await resultSet.ReadResultToEnd(mockReader, CancellationToken.None);
// ... Create a mock reader that will throw on read
var throwingReader = GetReader(new[] {new TestResultSet(5, 0)}, true, Constants.StandardQuery);
// If: I add a row with a reader that throws on read
// Then:
// ... I should get an exception
await Assert.ThrowsAnyAsync<DbException>(() => resultSet.AddRow(throwingReader));
// ... The row count should not have changed
Assert.Equal(Common.StandardRows, resultSet.RowCount);
}
[Fact]
public async Task AddRowSuccess()
{
@@ -363,7 +385,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
private static DbDataReader GetReader(TestResultSet[] dataSet, bool throwOnRead, string query)
{
var info = Common.CreateTestConnectionInfo(dataSet, throwOnRead);
var info = Common.CreateTestConnectionInfo(dataSet, false, throwOnRead);
var connection = info.Factory.CreateSqlConnection(ConnectionService.BuildConnectionString(info.ConnectionDetails));
var command = connection.CreateCommand();
command.CommandText = query;

View File

@@ -204,7 +204,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I request to execute a valid query with all batches as no op
var workspaceService = GetDefaultWorkspaceService(string.Format("{0}\r\nGO\r\n{0}", Common.NoOpQuery));
var queryService = Common.GetPrimedExecutionService(null, true, false, workspaceService);
var queryService = Common.GetPrimedExecutionService(null, true, false, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams { QuerySelection = Common.WholeDocument, OwnerUri = Constants.OwnerUri };
var efv = new EventFlowValidator<ExecuteRequestResult>()
@@ -239,7 +239,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I request to execute a valid query with no results
var workspaceService = GetDefaultWorkspaceService(Constants.StandardQuery);
var queryService = Common.GetPrimedExecutionService(null, true, false, workspaceService);
var queryService = Common.GetPrimedExecutionService(null, true, false, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams { QuerySelection = Common.WholeDocument, OwnerUri = Constants.OwnerUri};
var efv = new EventFlowValidator<ExecuteRequestResult>()
@@ -266,8 +266,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I request to execute a valid query with results
var workspaceService = GetDefaultWorkspaceService(Constants.StandardQuery);
var queryService = Common.GetPrimedExecutionService(Common.StandardTestDataSet, true, false,
workspaceService);
var queryService = Common.GetPrimedExecutionService(Common.StandardTestDataSet, true, false, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams { OwnerUri = Constants.OwnerUri, QuerySelection = Common.WholeDocument};
var efv = new EventFlowValidator<ExecuteRequestResult>()
@@ -295,7 +294,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// ... I request to execute a valid query with one batch and multiple result sets
var workspaceService = GetDefaultWorkspaceService(Constants.StandardQuery);
var dataset = new[] {Common.StandardTestResultSet, Common.StandardTestResultSet};
var queryService = Common.GetPrimedExecutionService(dataset, true, false, workspaceService);
var queryService = Common.GetPrimedExecutionService(dataset, true, false, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams { OwnerUri = Constants.OwnerUri, QuerySelection = Common.WholeDocument};
var efv = new EventFlowValidator<ExecuteRequestResult>()
@@ -322,7 +321,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I request a to execute a valid query with multiple batches
var workspaceService = GetDefaultWorkspaceService(string.Format("{0}\r\nGO\r\n{0}", Constants.StandardQuery));
var queryService = Common.GetPrimedExecutionService(Common.StandardTestDataSet, true, false, workspaceService);
var queryService = Common.GetPrimedExecutionService(Common.StandardTestDataSet, true, false, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams { OwnerUri = Constants.OwnerUri, QuerySelection = Common.WholeDocument};
var efv = new EventFlowValidator<ExecuteRequestResult>()
@@ -354,7 +353,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I request to execute a query using a file URI that isn't connected
var workspaceService = GetDefaultWorkspaceService(Constants.StandardQuery);
var queryService = Common.GetPrimedExecutionService(null, false, false, workspaceService);
var queryService = Common.GetPrimedExecutionService(null, false, false, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams { OwnerUri = "notConnected", QuerySelection = Common.WholeDocument };
var efv = new EventFlowValidator<ExecuteRequestResult>()
@@ -376,7 +375,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I request to execute a query
var workspaceService = GetDefaultWorkspaceService(Constants.StandardQuery);
var queryService = Common.GetPrimedExecutionService(null, true, false, workspaceService);
var queryService = Common.GetPrimedExecutionService(null, true, false, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams { OwnerUri = Constants.OwnerUri, QuerySelection = Common.WholeDocument};
// Note, we don't care about the results of the first request
@@ -404,7 +403,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I request to execute a query
var workspaceService = GetDefaultWorkspaceService(Constants.StandardQuery);
var queryService = Common.GetPrimedExecutionService(null, true, false, workspaceService);
var queryService = Common.GetPrimedExecutionService(null, true, false, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams { OwnerUri = Constants.OwnerUri, QuerySelection = Common.WholeDocument};
// Note, we don't care about the results of the first request
@@ -435,7 +434,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// If:
// ... I request to execute a query that is invalid
var workspaceService = GetDefaultWorkspaceService(Constants.StandardQuery);
var queryService = Common.GetPrimedExecutionService(null, true, true, workspaceService);
var queryService = Common.GetPrimedExecutionService(null, true, true, false, workspaceService);
var queryParams = new ExecuteDocumentSelectionParams {OwnerUri = Constants.OwnerUri, QuerySelection = Common.WholeDocument};
var efv = new EventFlowValidator<ExecuteRequestResult>()
@@ -458,7 +457,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
// [Fact]
public async Task SimpleExecuteErrorWithNoResultsTest()
{
var queryService = Common.GetPrimedExecutionService(null, true, false, null);
var queryService = Common.GetPrimedExecutionService(null, true, false, false, null);
var queryParams = new SimpleExecuteParams { OwnerUri = Constants.OwnerUri, QueryString = Constants.StandardQuery };
var efv = new EventFlowValidator<SimpleExecuteResult>()
.AddSimpleExecuteErrorValidator(SR.QueryServiceResultSetHasNoResults)
@@ -480,7 +479,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
[Fact]
public async Task SimpleExecuteVerifyResultsTest()
{
var queryService = Common.GetPrimedExecutionService(Common.StandardTestDataSet, true, false, null);
var queryService = Common.GetPrimedExecutionService(Common.StandardTestDataSet, true, false, false, null);
var queryParams = new SimpleExecuteParams { OwnerUri = Constants.OwnerUri, QueryString = Constants.StandardQuery };
var efv = new EventFlowValidator<SimpleExecuteResult>()
.AddSimpleExecuteQueryResultValidator(Common.StandardTestDataSet)
@@ -504,7 +503,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
[Fact]
public async Task SimpleExecuteMultipleQueriesTest()
{
var queryService = Common.GetPrimedExecutionService(Common.StandardTestDataSet, true, false, null);
var queryService = Common.GetPrimedExecutionService(Common.StandardTestDataSet, true, false, false, null);
var queryParams = new SimpleExecuteParams { OwnerUri = Constants.OwnerUri, QueryString = Constants.StandardQuery };
var efv1 = new EventFlowValidator<SimpleExecuteResult>()
.AddSimpleExecuteQueryResultValidator(Common.StandardTestDataSet)