diff --git a/spanner-ado-net/spanner-ado-net-tests/ReaderTests.cs b/spanner-ado-net/spanner-ado-net-tests/ReaderTests.cs index eb67ce89..8fade694 100644 --- a/spanner-ado-net/spanner-ado-net-tests/ReaderTests.cs +++ b/spanner-ado-net/spanner-ado-net-tests/ReaderTests.cs @@ -486,6 +486,49 @@ public async Task Exception_thrown_from_ExecuteReaderAsync([Values(PrepareOrNot. Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateException(new RpcException(new Status(StatusCode.Internal, "test")))); Assert.That(async () => await cmd.ExecuteReaderAsync(), Throws.Exception.TypeOf()); } + + [NonParallelizable] + [Test] + public async Task Exception_thrown_from_Read_and_ReadAsync([Values(true, false)] bool asyncRead) + { + var oldStyle = Environment.GetEnvironmentVariable("SPANNER_ADO_COMMUNICATION_STYLE"); + Environment.SetEnvironmentVariable("SPANNER_ADO_COMMUNICATION_STYLE", "ServerStreaming"); + SpannerPool.CloseSpannerLib(); + try + { + const string sql = "SELECT Id FROM test_table"; + Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateSingleColumnResultSet(new V1.Type { Code = TypeCode.Int64 }, "Id", 1L, 2L)); + + var executionTime = ExecutionTime.StreamException( + new RpcException(new Status(StatusCode.Internal, "test error")), + 1, + new System.Collections.Concurrent.BlockingCollection()); + executionTime.AlwaysAllowWrite(); + Fixture.SpannerMock.AddOrUpdateExecutionTime(nameof(MockSpannerService.ExecuteStreamingSql), executionTime); + + await using var conn = await OpenConnectionAsync(); + await using var cmd = new SpannerCommand(sql, conn); + await using var reader = await cmd.ExecuteReaderAsync(); + + if (asyncRead) + { + Assert.That(await reader.ReadAsync(), Is.True); + Assert.That(reader.GetInt64(0), Is.EqualTo(1L)); + Assert.That(async () => await reader.ReadAsync(), Throws.Exception.TypeOf()); + } + else + { + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetInt64(0), Is.EqualTo(1L)); + Assert.That(() => reader.Read(), Throws.Exception.TypeOf()); + } + } + finally + { + Environment.SetEnvironmentVariable("SPANNER_ADO_COMMUNICATION_STYLE", oldStyle); + SpannerPool.CloseSpannerLib(); + } + } [Ignore("Require multi-statement support")] [Test] diff --git a/spanner-ado-net/spanner-ado-net/SpannerDataReader.cs b/spanner-ado-net/spanner-ado-net/SpannerDataReader.cs index 54273ce2..cb077f28 100644 --- a/spanner-ado-net/spanner-ado-net/SpannerDataReader.cs +++ b/spanner-ado-net/spanner-ado-net/SpannerDataReader.cs @@ -137,13 +137,20 @@ public override void Close() public override bool Read() { - if (!InternalRead()) + try { - _hasReadData = true; - _currentRow = LibRows.Next(); + if (!InternalRead()) + { + _hasReadData = true; + _currentRow = LibRows.Next(); + } + _hasData = _hasData || _currentRow != null; + return _currentRow != null; + } + catch (SpannerException exception) + { + throw SpannerDbException.TranslateException(exception); } - _hasData = _hasData || _currentRow != null; - return _currentRow != null; } public override async Task ReadAsync(CancellationToken cancellationToken) @@ -184,8 +191,15 @@ private bool InternalRead() private bool CheckForRows() { - _tempRow ??= LibRows.Next(); - return _tempRow != null; + try + { + _tempRow ??= LibRows.Next(); + return _tempRow != null; + } + catch (SpannerException exception) + { + throw SpannerDbException.TranslateException(exception); + } } public override DataTable? GetSchemaTable() @@ -916,18 +930,25 @@ public override bool IsDBNull(int ordinal) public override bool NextResult() { - CheckNotClosed(); - if (IsSingleRow || IsSingleResult) + try { - return false; + CheckNotClosed(); + if (IsSingleRow || IsSingleResult) + { + return false; + } + _currentRow = null; + _tempRow = null; + _hasData = false; + _hasReadData = false; + _metadata = null; + _stats = null; + return LibRows.NextResultSet(); + } + catch (SpannerException exception) + { + throw SpannerDbException.TranslateException(exception); } - _currentRow = null; - _tempRow = null; - _hasData = false; - _hasReadData = false; - _metadata = null; - _stats = null; - return LibRows.NextResultSet(); } public override IEnumerator GetEnumerator()