@@ -412,23 +412,67 @@ public final class Connection {
412
412
///
413
413
/// db.trace { SQL in print(SQL) }
414
414
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 ) ? ) {
415
423
guard let callback = callback else {
416
- sqlite3_trace ( handle, nil , nil )
424
+ sqlite3_trace ( handle, nil /* xCallback */ , nil /* pCtx */ )
417
425
trace = nil
418
426
return
419
427
}
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
+ }
426
437
} ,
427
438
unsafeBitCast ( box, to: UnsafeMutableRawPointer . self)
428
439
)
429
440
trace = box
430
441
}
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
432
476
fileprivate var trace : Trace ?
433
477
434
478
/// Registers a callback to be invoked whenever a row is inserted, updated,
0 commit comments