Skip to content

Commit 05cf90f

Browse files
committed
Query interrupt support
Adds the ability to interrupt a database connection during a long-running query. Signed-off-by: Stephen Celis <stephen@stephencelis.com>
1 parent 24cd405 commit 05cf90f

File tree

4 files changed

+26
-1
lines changed

4 files changed

+26
-1
lines changed

SQLite Tests/DatabaseTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,22 @@ class DatabaseTests: SQLiteTestCase {
264264
AssertSQL("INSERT INTO users (email, admin) VALUES ('alice@example.com', 1)", 2)
265265
}
266266

267+
func test_interrupt_interruptsLongRunningQuery() {
268+
insertUsers(map("abcdefghijklmnopqrstuvwxyz") { String($0) })
269+
db.create(function: "sleep") { args in
270+
usleep(UInt32(Double(args[0] as? Double ?? Double(args[0] as? Int64 ?? 1)) * 1_000_000))
271+
return nil
272+
}
273+
274+
let stmt = db.prepare("SELECT *, sleep(?) FROM users", 0.1)
275+
stmt.run()
276+
XCTAssert(!stmt.failed)
277+
278+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(10 * NSEC_PER_MSEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), db.interrupt)
279+
stmt.run()
280+
XCTAssert(stmt.failed)
281+
}
282+
267283
func test_userVersion_getsAndSetsUserVersion() {
268284
XCTAssertEqual(0, db.userVersion)
269285
db.userVersion = 1

SQLite Tests/TestHelper.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ class SQLiteTestCase: XCTestCase {
4040
}
4141

4242
func insertUsers(names: String...) {
43+
insertUsers(names)
44+
}
45+
46+
func insertUsers(names: [String]) {
4347
for name in names { insertUser(name) }
4448
}
4549

SQLite/Database.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,11 @@ public final class Database {
343343
return run("ROLLBACK TO SAVEPOINT \(quote(literal: savepointName))")
344344
}
345345

346+
/// Interrupts any long-running queries.
347+
public func interrupt() {
348+
sqlite3_interrupt(handle)
349+
}
350+
346351
// MARK: - Configuration
347352

348353
public var foreignKeys: Bool {

SQLite/Statement.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ public final class Statement {
194194
self.status = block()
195195
if self.failed {
196196
self.reason = String.fromCString(sqlite3_errmsg(self.database.handle))
197-
assert(self.status == SQLITE_CONSTRAINT, "\(self.reason!)")
197+
assert(self.status == SQLITE_CONSTRAINT || self.status == SQLITE_INTERRUPT, "\(self.reason!)")
198198
}
199199
}
200200
}

0 commit comments

Comments
 (0)