@@ -357,31 +357,43 @@ public final class Connection {
357357 /// times it’s been called for this lock. If it returns `true`, it will
358358 /// try again. If it returns `false`, no further attempts will be made.
359359 public func busyHandler( callback: ( ( tries: Int ) -> Bool ) ? ) {
360- if let callback = callback {
361- busyHandler = { callback ( tries: Int ( $0) ) ? 1 : 0 }
362- } else {
360+ guard let callback = callback else {
361+ sqlite3_busy_handler ( handle, nil , nil )
363362 busyHandler = nil
363+ return
364364 }
365+
366+ let box : BusyHandler = { callback ( tries: Int ( $0) ) ? 1 : 0 }
367+ sqlite3_busy_handler ( handle, { callback, tries in
368+ unsafeBitCast ( callback, BusyHandler . self) ( tries)
369+ } , unsafeBitCast ( box, UnsafeMutablePointer< Void> . self ) )
370+ busyHandler = box
365371 }
366- private var busyHandler : _SQLiteBusyHandlerCallback ?
372+ private typealias BusyHandler = @convention ( block) Int32 -> Int32
373+ private var busyHandler : BusyHandler ?
367374
368375 /// Sets a handler to call when a statement is executed with the compiled
369376 /// SQL.
370377 ///
371378 /// - Parameter callback: This block is invoked when a statement is executed
372- /// with the compiled SQL as its argument. E.g., pass `print` to act as a
373- /// logger.
379+ /// with the compiled SQL as its argument.
374380 ///
375- /// db.trace( print)
381+ /// db.trace { SQL in print(SQL) }
376382 public func trace( callback: ( String -> Void ) ? ) {
377- if let callback = callback {
378- trace = { callback ( String . fromCString ( $0) !) }
379- } else {
383+ guard let callback = callback else {
384+ sqlite3_trace ( handle, nil , nil )
380385 trace = nil
386+ return
381387 }
382- _SQLiteTrace ( handle, trace)
388+
389+ let box : Trace = { callback ( String . fromCString ( $0) !) }
390+ sqlite3_trace ( handle, { callback, SQL in
391+ unsafeBitCast ( callback, Trace . self) ( SQL)
392+ } , unsafeBitCast ( box, UnsafeMutablePointer< Void> . self ) )
393+ trace = box
383394 }
384- private var trace : _SQLiteTraceCallback ?
395+ private typealias Trace = @convention ( block) UnsafePointer < Int8 > -> Void
396+ private var trace : Trace ?
385397
386398 /// Registers a callback to be invoked whenever a row is inserted, updated,
387399 /// or deleted in a rowid table.
@@ -390,53 +402,75 @@ public final class Connection {
390402 /// `.Insert`, `.Update`, or `.Delete`), database name, table name, and
391403 /// rowid.
392404 public func updateHook( callback: ( ( operation: Operation , db: String , table: String , rowid: Int64 ) -> Void ) ? ) {
393- if let callback = callback {
394- updateHook = { operation, db, table, rowid in
395- callback (
396- operation: Operation ( rawValue: operation) ,
397- db: String . fromCString ( db) !,
398- table: String . fromCString ( table) !,
399- rowid: rowid
400- )
401- }
402- } else {
405+ guard let callback = callback else {
406+ sqlite3_update_hook ( handle, nil , nil )
403407 updateHook = nil
408+ return
404409 }
405- _SQLiteUpdateHook ( handle, updateHook)
410+
411+ let box : UpdateHook = {
412+ callback (
413+ operation: Operation ( rawValue: $0) ,
414+ db: String . fromCString ( $1) !,
415+ table: String . fromCString ( $2) !,
416+ rowid: $3
417+ )
418+ }
419+ sqlite3_update_hook ( handle, { callback, operation, db, table, rowid in
420+ unsafeBitCast ( callback, UpdateHook . self) ( operation, db, table, rowid)
421+ } , unsafeBitCast ( box, UnsafeMutablePointer< Void> . self ) )
422+ updateHook = box
406423 }
407- private var updateHook : _SQLiteUpdateHookCallback ?
424+ private typealias UpdateHook = @convention ( block) ( Int32 , UnsafePointer < Int8 > , UnsafePointer < Int8 > , Int64 ) -> Void
425+ private var updateHook : UpdateHook ?
408426
409427 /// Registers a callback to be invoked whenever a transaction is committed.
410428 ///
411429 /// - Parameter callback: A callback invoked whenever a transaction is
412430 /// committed. If this callback throws, the transaction will be rolled
413431 /// back.
414432 public func commitHook( callback: ( ( ) throws -> Void ) ? ) {
415- if let callback = callback {
416- commitHook = {
417- do {
418- try callback ( )
419- return 0
420- } catch {
421- return 1
422- }
423- }
424- } else {
433+ guard let callback = callback else {
434+ sqlite3_commit_hook ( handle, nil , nil )
425435 commitHook = nil
436+ return
426437 }
427- _SQLiteCommitHook ( handle, commitHook)
438+
439+ let box : CommitHook = {
440+ do {
441+ try callback ( )
442+ } catch {
443+ return 1
444+ }
445+ return 0
446+ }
447+ sqlite3_commit_hook ( handle, { callback in
448+ unsafeBitCast ( callback, CommitHook . self) ( )
449+ } , unsafeBitCast ( box, UnsafeMutablePointer< Void> . self ) )
450+ commitHook = box
428451 }
429- private var commitHook : _SQLiteCommitHookCallback ?
452+ private typealias CommitHook = @convention ( block) ( ) -> Int32
453+ private var commitHook : CommitHook ?
430454
431455 /// Registers a callback to be invoked whenever a transaction rolls back.
432456 ///
433457 /// - Parameter callback: A callback invoked when a transaction is rolled
434458 /// back.
435- public func rollbackHook( callback: _SQLiteRollbackHookCallback ? ) {
436- rollbackHook = callback
437- _SQLiteRollbackHook ( handle, rollbackHook)
459+ public func rollbackHook( callback: ( ( ) -> Void ) ? ) {
460+ guard let callback = callback else {
461+ sqlite3_rollback_hook ( handle, nil , nil )
462+ rollbackHook = nil
463+ return
464+ }
465+
466+ let box : RollbackHook = { callback ( ) }
467+ sqlite3_rollback_hook ( handle, { callback in
468+ unsafeBitCast ( callback, RollbackHook . self) ( )
469+ } , unsafeBitCast ( box, UnsafeMutablePointer< Void> . self ) )
470+ rollbackHook = box
438471 }
439- private var rollbackHook : _SQLiteRollbackHookCallback ?
472+ private typealias RollbackHook = @convention ( block) ( ) -> Void
473+ private var rollbackHook : RollbackHook ?
440474
441475 /// Creates or redefines a custom SQL function.
442476 ///
@@ -459,8 +493,7 @@ public final class Connection {
459493 /// parameters and should return a raw SQL value (or nil).
460494 public func createFunction( function: String , argumentCount: UInt ? = nil , deterministic: Bool = false , _ block: ( args: [ Binding ? ] ) -> Binding ? ) {
461495 let argc = argumentCount. map { Int ( $0) } ?? - 1
462- if functions [ function] == nil { self . functions [ function] = [ : ] }
463- functions [ function] ? [ argc] = { context, argc, argv in
496+ let box : Function = { context, argc, argv in
464497 let arguments : [ Binding ? ] = ( 0 ..< Int ( argc) ) . map { idx in
465498 let value = argv [ idx]
466499 switch sqlite3_value_type ( value) {
@@ -493,10 +526,18 @@ public final class Connection {
493526 fatalError ( " unsupported result type: \( result) " )
494527 }
495528 }
496- try ! check ( _SQLiteCreateFunction ( handle, function, Int32 ( argc) , deterministic ? 1 : 0 , functions [ function] ? [ argc] ) )
529+ var flags = SQLITE_UTF8
530+ if deterministic {
531+ flags |= SQLITE_DETERMINISTIC
532+ }
533+ sqlite3_create_function_v2 ( handle, function, Int32 ( argc) , flags, unsafeBitCast ( box, UnsafeMutablePointer< Void> . self ) , { context, argc, value in
534+ unsafeBitCast ( sqlite3_user_data ( context) , Function . self) ( context, argc, value)
535+ } , nil , nil , nil )
536+ if functions [ function] == nil { self . functions [ function] = [ : ] }
537+ functions [ function] ? [ argc] = box
497538 }
498- private var functions = [ String : [ Int : _SQLiteCreateFunctionCallback ] ] ( )
499-
539+ private typealias Function = @ convention ( block ) ( COpaquePointer , Int32 , UnsafeMutablePointer < COpaquePointer > ) -> Void
540+ private var functions = [ String : [ Int : Function ] ] ( )
500541
501542 /// The return type of a collation comparison function.
502543 public typealias ComparisonResult = NSComparisonResult
@@ -510,12 +551,16 @@ public final class Connection {
510551 /// - block: A collation function that takes two strings and returns the
511552 /// comparison result.
512553 public func createCollation( collation: String , _ block: ( lhs: String , rhs: String ) -> ComparisonResult ) {
513- collations [ collation ] = { lhs, rhs in
514- Int32 ( block ( lhs: String . fromCString ( lhs) !, rhs: String . fromCString ( rhs) !) . rawValue)
554+ let box : Collation = { lhs, rhs in
555+ Int32 ( block ( lhs: String . fromCString ( UnsafePointer < Int8 > ( lhs) ) !, rhs: String . fromCString ( UnsafePointer < Int8 > ( rhs) ) !) . rawValue)
515556 }
516- try ! check ( _SQLiteCreateCollation ( handle, collation, collations [ collation] ) )
557+ try ! check ( sqlite3_create_collation_v2 ( handle, collation, SQLITE_UTF8, unsafeBitCast ( box, UnsafeMutablePointer< Void> . self ) , { callback, _, lhs, _, rhs in
558+ unsafeBitCast ( callback, Collation . self) ( lhs, rhs)
559+ } , nil ) )
560+ collations [ collation] = box
517561 }
518- private var collations = [ String: _SQLiteCreateCollationCallback] ( )
562+ private typealias Collation = @convention ( block) ( UnsafePointer < Void > , UnsafePointer < Void > ) -> Int32
563+ private var collations = [ String: Collation] ( )
519564
520565 // MARK: - Error Handling
521566
0 commit comments