@@ -92,6 +92,7 @@ private final class FreeTDSConnection: @unchecked Sendable {
9292 private let database : String
9393 private let lock = NSLock ( )
9494 private var _isConnected = false
95+ private var _isCancelled = false
9596
9697 var isConnected : Bool {
9798 lock. lock ( )
@@ -172,6 +173,16 @@ private final class FreeTDSConnection: @unchecked Sendable {
172173 }
173174 }
174175
176+ func cancelCurrentQuery( ) {
177+ lock. lock ( )
178+ _isCancelled = true
179+ let proc = dbproc
180+ lock. unlock ( )
181+
182+ guard let proc else { return }
183+ dbcancel ( proc)
184+ }
185+
175186 func executeQuery( _ query: String ) async throws -> FreeTDSQueryResult {
176187 let queryToRun = String ( query)
177188 return try await pluginDispatchAsync ( on: queue) { [ self ] in
@@ -186,6 +197,10 @@ private final class FreeTDSConnection: @unchecked Sendable {
186197
187198 _ = dbcanquery ( proc)
188199
200+ lock. lock ( )
201+ _isCancelled = false
202+ lock. unlock ( )
203+
189204 freetdsLastError = " "
190205 if dbcmd ( proc, query) == FAIL {
191206 throw MSSQLPluginError . queryFailed ( " Failed to prepare query " )
@@ -232,6 +247,14 @@ private final class FreeTDSConnection: @unchecked Sendable {
232247 if rowCode == Int32 ( NO_MORE_ROWS) { break }
233248 if rowCode == FAIL { break }
234249
250+ lock. lock ( )
251+ let cancelled = _isCancelled
252+ if cancelled { _isCancelled = false }
253+ lock. unlock ( )
254+ if cancelled {
255+ throw MSSQLPluginError . queryFailed ( " Query cancelled " )
256+ }
257+
235258 var row : [ String ? ] = [ ]
236259 for i in 1 ... numCols {
237260 let len = dbdatlen ( proc, Int32 ( i) )
@@ -386,6 +409,16 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable {
386409 )
387410 }
388411
412+ func cancelQuery( ) throws {
413+ freeTDSConn? . cancelCurrentQuery ( )
414+ }
415+
416+ func applyQueryTimeout( _ seconds: Int ) async throws {
417+ guard seconds > 0 else { return }
418+ let ms = seconds * 1_000
419+ _ = try await execute ( query: " SET LOCK_TIMEOUT \( ms) " )
420+ }
421+
389422 func executeParameterized( query: String , parameters: [ String ? ] ) async throws -> PluginQueryResult {
390423 guard !parameters. isEmpty else {
391424 return try await execute ( query: query)
0 commit comments