diff --git a/src/LibSql.Http.Client/Exceptions/LibSqlHttpClientException.cs b/src/LibSql.Http.Client/Exceptions/LibSqlHttpClientException.cs index 4707ecf..1303ae8 100644 --- a/src/LibSql.Http.Client/Exceptions/LibSqlHttpClientException.cs +++ b/src/LibSql.Http.Client/Exceptions/LibSqlHttpClientException.cs @@ -1,34 +1,7 @@ -using LibSql.Http.Client.Response; - namespace LibSql.Http.Client.Exceptions; /// public class LibSqlClientException(string message, Exception? innerException = default) : Exception(message, innerException) { - private const string TabConstant = "\t"; - - /// - /// Create exception using errors from pipeline request - /// - /// Errors from pipeline response - public LibSqlClientException(IReadOnlyCollection executionErrors) : this( - FormatErrorMessage(executionErrors)) - { - } - - private static string FormatErrorMessage(IReadOnlyCollection executionErrors) - { - var joinedMessages = string.Join( - Environment.NewLine, - executionErrors.Select( - (error, index) => - { - var codePart = error.Code is null ? string.Empty : $"({error.Code}) "; - - return $"{TabConstant}[{index}]: {codePart}{error.Message}"; - })); - - return $"[LibSqlPipelineError] The request failed.{Environment.NewLine}{joinedMessages}"; - } -} \ No newline at end of file +} diff --git a/src/LibSql.Http.Client/Exceptions/LibSqlHttpClientExecutionException.cs b/src/LibSql.Http.Client/Exceptions/LibSqlHttpClientExecutionException.cs new file mode 100644 index 0000000..9cf2810 --- /dev/null +++ b/src/LibSql.Http.Client/Exceptions/LibSqlHttpClientExecutionException.cs @@ -0,0 +1,44 @@ +using LibSql.Http.Client.Response; + +namespace LibSql.Http.Client.Exceptions; + +/// +public class LibSqlClientExecutionException : LibSqlClientException +{ + private const string TabConstant = "\t"; + + /// + /// Create exception using errors from pipeline request + /// + /// Errors from pipeline response + public LibSqlClientExecutionException(IReadOnlyCollection executionErrors) : base( + FormatErrorMessage(executionErrors)) + { + ExecutionErrors = executionErrors; + } + + /// + /// Errors from pipeline response + /// + public IReadOnlyCollection ExecutionErrors { get; } + + /// + /// First error from pipeline response + /// + public ExecutionError Error => ExecutionErrors.First(); + + private static string FormatErrorMessage(IReadOnlyCollection executionErrors) + { + var joinedMessages = string.Join( + Environment.NewLine, + executionErrors.Select( + (error, index) => + { + var codePart = error.Code is null ? string.Empty : $"({error.Code}) "; + + return $"{TabConstant}[{index}]: {codePart}{error.Message}"; + })); + + return $"[LibSqlPipelineError] The request failed.{Environment.NewLine}{joinedMessages}"; + } +} diff --git a/src/LibSql.Http.Client/Response/ResultReader.cs b/src/LibSql.Http.Client/Response/ResultReader.cs index d36aaf6..a02a112 100644 --- a/src/LibSql.Http.Client/Response/ResultReader.cs +++ b/src/LibSql.Http.Client/Response/ResultReader.cs @@ -41,7 +41,7 @@ public void Dispose() public void ThrowIfError() { if (errors.Length > 0) - throw new LibSqlClientException(errors); + throw new LibSqlClientExecutionException(errors); } public bool HasMoreResults() diff --git a/test/LibSql.Http.Client.Tests/Integration/RollbackTests.cs b/test/LibSql.Http.Client.Tests/Integration/RollbackTests.cs index cac0bc7..b3050a7 100644 --- a/test/LibSql.Http.Client.Tests/Integration/RollbackTests.cs +++ b/test/LibSql.Http.Client.Tests/Integration/RollbackTests.cs @@ -38,7 +38,7 @@ public async Task CheckRollbackWhenOneCommandIsInvalid() var failingAction = () => LibSqlClient.ExecuteMultipleAsync(statements, TransactionMode.WriteImmediate); - await failingAction.Should().ThrowExactlyAsync(); + await failingAction.Should().ThrowExactlyAsync(); var afterCount = await LibSqlClient.ExecuteScalarAsync(TestData.CountSql); diff --git a/test/LibSql.Http.Client.Tests/LibSqlHttpClientTestsDefault.cs b/test/LibSql.Http.Client.Tests/LibSqlHttpClientTestsDefault.cs index a6f9320..a1ae6ed 100644 --- a/test/LibSql.Http.Client.Tests/LibSqlHttpClientTestsDefault.cs +++ b/test/LibSql.Http.Client.Tests/LibSqlHttpClientTestsDefault.cs @@ -18,7 +18,7 @@ public void ConstructorShouldFailIfUrlIsNull() action.Should().ThrowExactly(); } - + [Theory] [JsonFileData("Data/execute-response-no-error-no-result.json", true)] public void ShouldAllowUseDifferentCredentials(JsonElement response) @@ -29,7 +29,7 @@ public void ShouldAllowUseDifferentCredentials(JsonElement response) handler.LastSentRequest!.Uri.Should().Be("https://another.libsql.test/v3/pipeline"); } - + [Theory] [JsonFileData("Data/execute-response-with-error.json", true)] public async Task ShouldThrowExceptionIfResultContainsError( @@ -43,7 +43,7 @@ public async Task ShouldThrowExceptionIfResultContainsError( sql, TestDataJsonSerializerContext.Default.ResultSetTestModel); - await action.Should().ThrowExactlyAsync(); + await action.Should().ThrowExactlyAsync(); handler.LastSentRequest.Should().NotBeNull(); handler.LastSentRequest!.Body.Should().BeEquivalentTo(JsonSerializer.Serialize(request)); } @@ -240,14 +240,17 @@ public async Task ShouldParseMultipleResults(JsonElement response, ResultSetTest { var (_, client) = CreateClient(response); - var result = await client.QueryMultipleAsync(["SELECT * FROM table1", "SELECT * FROM TABLE 2"], TransactionMode.WriteImmediate); + var result = await client.QueryMultipleAsync( + ["SELECT * FROM table1", "SELECT * FROM TABLE 2"], + TransactionMode.WriteImmediate); result.Count.Should().Be(expected.Length); for (var i = 0; i < expected.Length; i++) { result.HasMoreResults().Should().BeTrue(); - result.Read(TestDataJsonSerializerContext.Default.ResultSetTestModel).ToList().Should().BeEquivalentTo(expected[i]); + result.Read(TestDataJsonSerializerContext.Default.ResultSetTestModel).ToList().Should() + .BeEquivalentTo(expected[i]); } result.HasMoreResults().Should().BeFalse(); @@ -258,4 +261,4 @@ private static (MockedJsonHttpHandler, LibSqlHttpClient) CreateClient(JsonElemen var handler = new MockedJsonHttpHandler(response); return (handler, new LibSqlHttpClient(handler, null, "token")); } -} \ No newline at end of file +}