Skip to content

Commit

Permalink
Add support for command cancellation
Browse files Browse the repository at this point in the history
  • Loading branch information
Giorgi committed Jul 21, 2024
1 parent 2c78e20 commit fe02f4c
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 4 deletions.
3 changes: 3 additions & 0 deletions DuckDB.NET.Bindings/NativeMethods/NativeMethods.Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public static class Startup
[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_disconnect")]
public static extern void DuckDBDisconnect(out IntPtr connection);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_interrupt")]
public static extern void DuckDBInterrupt(IntPtr connection);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_library_version")]
public static extern IntPtr DuckDBLibraryVersion();
}
Expand Down
7 changes: 6 additions & 1 deletion DuckDB.NET.Data/DuckDBCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@ public DuckDBCommand(string commandText, DuckDBConnection connection)
}

public override void Cancel()
{ }
{
if (connection != null)
{
NativeMethods.Startup.DuckDBInterrupt(connection.NativeConnection.DangerousGetHandle());
}
}

public override int ExecuteNonQuery()
{
Expand Down
13 changes: 12 additions & 1 deletion DuckDB.NET.Data/Internal/PreparedStatement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,18 @@ public DuckDBResult Execute(DuckDBParameterCollection parameterCollection, bool
{
var errorMessage = NativeMethods.Query.DuckDBResultError(ref queryResult).ToManagedString(false);
queryResult.Dispose();
throw new DuckDBException(string.IsNullOrEmpty(errorMessage) ? "DuckDBQuery failed" : errorMessage, status);

if (string.IsNullOrEmpty(errorMessage))
{
errorMessage = "DuckDB execution failed";
}

if (errorMessage.StartsWith("INTERRUPT Error"))
{
throw new OperationCanceledException();
}

throw new DuckDBException(errorMessage, status);
}

return queryResult;
Expand Down
18 changes: 18 additions & 0 deletions DuckDB.NET.Test/DuckDBDataReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Data;
using DuckDB.NET.Native;
using Xunit;
using System.Threading.Tasks;
using System.Threading;

namespace DuckDB.NET.Test;

Expand Down Expand Up @@ -356,4 +358,20 @@ public void ReadDecimalSchemaWithoutTableRow()
schemaTable.Rows[0]["NumericScale"].Should().Be(0);
schemaTable.Rows[0]["NumericPrecision"].Should().Be(0);
}

[Fact]
public async Task CancellingLongRunningQueryThrowsOperationCancelledException()
{
Command.CommandText = @"create table cnt as WITH RECURSIVE
cnt(x) AS (
SELECT 1
UNION ALL
SELECT x+1 FROM cnt
where x < 300000
) select * from cnt;";

var source = new CancellationTokenSource(1000);

await Command.Invoking(async c => await c.ExecuteReaderAsync(source.Token)).Should().ThrowAsync<OperationCanceledException>();
}
}
3 changes: 1 addition & 2 deletions DuckDB.NET.Test/ExecuteNonQueryTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using DuckDB.NET.Data;
using FluentAssertions;
using FluentAssertions;
using System.Collections.Generic;
using Xunit;

Expand Down

0 comments on commit fe02f4c

Please sign in to comment.