Skip to content

Commit 336faa1

Browse files
committed
Use sqlite3_trace_v2 where available
1 parent b392eaf commit 336faa1

File tree

2 files changed

+58
-8
lines changed

2 files changed

+58
-8
lines changed

SQLite/Core/Connection.swift

+52-8
Original file line numberDiff line numberDiff line change
@@ -412,23 +412,67 @@ public final class Connection {
412412
///
413413
/// db.trace { SQL in print(SQL) }
414414
public func trace(_ callback: ((String) -> Void)?) {
415+
if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
416+
trace_v2(callback)
417+
} else {
418+
trace_v1(callback)
419+
}
420+
}
421+
422+
fileprivate func trace_v1(_ callback: ((String) -> Void)?) {
415423
guard let callback = callback else {
416-
sqlite3_trace(handle, nil, nil)
424+
sqlite3_trace(handle, nil /* xCallback */, nil /* pCtx */)
417425
trace = nil
418426
return
419427
}
420-
421-
let box: Trace = { callback(String(cString: $0)) }
422-
sqlite3_trace(handle, {
423-
(callback: UnsafeMutableRawPointer?, SQL: UnsafePointer<Int8>?) in
424-
guard let callback = callback, let SQL = SQL else { return }
425-
unsafeBitCast(callback, to: Trace.self)(SQL)
428+
let box: Trace = { (pointer: UnsafeRawPointer) in
429+
callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
430+
}
431+
sqlite3_trace(handle,
432+
{
433+
(C: UnsafeMutableRawPointer?, SQL: UnsafePointer<Int8>?) in
434+
if let C = C, let SQL = SQL {
435+
unsafeBitCast(C, to: Trace.self)(SQL)
436+
}
426437
},
427438
unsafeBitCast(box, to: UnsafeMutableRawPointer.self)
428439
)
429440
trace = box
430441
}
431-
fileprivate typealias Trace = @convention(block) (UnsafePointer<Int8>) -> Void
442+
443+
@available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)
444+
fileprivate func trace_v2(_ callback: ((String) -> Void)?) {
445+
guard let callback = callback else {
446+
// If the X callback is NULL or if the M mask is zero, then tracing is disabled.
447+
sqlite3_trace_v2(handle, 0 /* mask */, nil /* xCallback */, nil /* pCtx */)
448+
trace = nil
449+
return
450+
}
451+
452+
let box: Trace = { (pointer: UnsafeRawPointer) in
453+
callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
454+
}
455+
sqlite3_trace_v2(handle,
456+
UInt32(SQLITE_TRACE_STMT) /* mask */,
457+
{
458+
// A trace callback is invoked with four arguments: callback(T,C,P,X).
459+
// The T argument is one of the SQLITE_TRACE constants to indicate why the
460+
// callback was invoked. The C argument is a copy of the context pointer.
461+
// The P and X arguments are pointers whose meanings depend on T.
462+
(T: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, X: UnsafeMutableRawPointer?) in
463+
if let P = P,
464+
let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) {
465+
unsafeBitCast(C, to: Trace.self)(expandedSQL)
466+
sqlite3_free(expandedSQL)
467+
}
468+
return Int32(0) // currently ignored
469+
},
470+
unsafeBitCast(box, to: UnsafeMutableRawPointer.self) /* pCtx */
471+
)
472+
trace = box
473+
}
474+
475+
fileprivate typealias Trace = @convention(block) (UnsafeRawPointer) -> Void
432476
fileprivate var trace: Trace?
433477

434478
/// Registers a callback to be invoked whenever a row is inserted, updated,

SQLiteTests/ConnectionTests.swift

+6
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ class ConnectionTests : SQLiteTestCase {
9494
AssertSQL("SELECT count(*) FROM users WHERE admin = 0", 4)
9595
}
9696

97+
func test_execute_comment() {
98+
try! db.run("-- this is a comment\nSELECT 1")
99+
AssertSQL("-- this is a comment", 0)
100+
AssertSQL("SELECT 1", 0)
101+
}
102+
97103
func test_transaction_executesBeginDeferred() {
98104
try! db.transaction(.deferred) {}
99105

0 commit comments

Comments
 (0)