Skip to content

Commit 24cd405

Browse files
committed
Plug C block memory leaks
The database connection can retain them well enough. Signed-off-by: Stephen Celis <stephen@stephencelis.com>
1 parent 1fea119 commit 24cd405

File tree

2 files changed

+23
-12
lines changed

2 files changed

+23
-12
lines changed

SQLite/Database.swift

+19-8
Original file line numberDiff line numberDiff line change
@@ -372,12 +372,16 @@ public final class Database {
372372
/// returns true, it will try again. If it returns false,
373373
/// no further attempts will be made.
374374
public func busy(callback: (Int -> Bool)?) {
375-
if let callback = callback {
376-
try { SQLiteBusyHandler(self.handle) { callback(Int($0)) ? 1 : 0 } }
377-
} else {
378-
try { SQLiteBusyHandler(self.handle, nil) }
375+
try {
376+
if let callback = callback {
377+
self.busy = { callback(Int($0)) ? 1 : 0 }
378+
} else {
379+
self.busy = nil
380+
}
381+
return SQLiteBusyHandler(self.handle, self.busy)
379382
}
380383
}
384+
private var busy: SQLiteBusyHandlerCallback?
381385

382386
/// Sets a handler to call when a statement is executed with the compiled
383387
/// SQL.
@@ -387,11 +391,13 @@ public final class Database {
387391
/// act as a logger.
388392
public func trace(callback: (String -> ())?) {
389393
if let callback = callback {
390-
SQLiteTrace(handle) { callback(String.fromCString($0)!) }
394+
trace = { callback(String.fromCString($0)!) }
391395
} else {
392-
SQLiteTrace(handle, nil)
396+
trace = nil
393397
}
398+
SQLiteTrace(handle, trace)
394399
}
400+
private var trace: SQLiteTraceCallback?
395401

396402
/// Creates or redefines a custom SQL function.
397403
///
@@ -412,7 +418,8 @@ public final class Database {
412418
/// should return a raw SQL value (or nil).
413419
public func create(#function: String, argc: Int = -1, deterministic: Bool = false, _ block: [Binding?] -> Binding?) {
414420
try {
415-
SQLiteCreateFunction(self.handle, function, Int32(argc), deterministic ? 1 : 0) { context, argc, argv in
421+
if self.functions[function] == nil { self.functions[function] = [:] }
422+
self.functions[function]?[argc] = { context, argc, argv in
416423
let arguments: [Binding?] = map(0..<Int(argc)) { idx in
417424
let value = argv[idx]
418425
switch sqlite3_value_type(value) {
@@ -447,8 +454,10 @@ public final class Database {
447454
assertionFailure("unsupported result type: \(result)")
448455
}
449456
}
457+
return SQLiteCreateFunction(self.handle, function, Int32(argc), deterministic ? 1 : 0, self.functions[function]?[argc])
450458
}
451459
}
460+
private var functions = [String: [Int: SQLiteCreateFunctionCallback]]()
452461

453462
/// The return type of a collation comparison function.
454463
public typealias ComparisonResult = NSComparisonResult
@@ -461,11 +470,13 @@ public final class Database {
461470
/// returns the comparison result.
462471
public func create(#collation: String, _ block: (String, String) -> ComparisonResult) {
463472
try {
464-
SQLiteCreateCollation(self.handle, collation) { lhs, rhs in
473+
self.collations[collation] = { lhs, rhs in
465474
return Int32(block(String.fromCString(lhs)!, String.fromCString(rhs)!).rawValue)
466475
}
476+
return SQLiteCreateCollation(self.handle, collation, self.collations[collation])
467477
}
468478
}
479+
private var collations = [String: SQLiteCreateCollationCallback]()
469480

470481
// MARK: - Error Handling
471482

SQLite/SQLite-Bridging.m

+4-4
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static int _SQLiteBusyHandler(void * context, int tries) {
3232

3333
int SQLiteBusyHandler(sqlite3 * handle, SQLiteBusyHandlerCallback callback) {
3434
if (callback) {
35-
return sqlite3_busy_handler(handle, _SQLiteBusyHandler, (__bridge_retained void *)callback); // FIXME: leak
35+
return sqlite3_busy_handler(handle, _SQLiteBusyHandler, (__bridge void *)callback);
3636
} else {
3737
return sqlite3_busy_handler(handle, 0, 0);
3838
}
@@ -44,7 +44,7 @@ static void _SQLiteTrace(void * context, const char * SQL) {
4444

4545
void SQLiteTrace(sqlite3 * handle, SQLiteTraceCallback callback) {
4646
if (callback) {
47-
sqlite3_trace(handle, _SQLiteTrace, (__bridge_retained void *)callback); // FIXME: leak
47+
sqlite3_trace(handle, _SQLiteTrace, (__bridge void *)callback);
4848
} else {
4949
sqlite3_trace(handle, 0, 0);
5050
}
@@ -62,7 +62,7 @@ int SQLiteCreateFunction(sqlite3 * handle, const char * name, int argc, int dete
6262
flags |= SQLITE_DETERMINISTIC;
6363
#endif
6464
}
65-
return sqlite3_create_function_v2(handle, name, -1, flags, (__bridge_retained void *)callback, &_SQLiteCreateFunction, 0, 0, 0); // FIXME: leak
65+
return sqlite3_create_function_v2(handle, name, -1, flags, (__bridge void *)callback, &_SQLiteCreateFunction, 0, 0, 0);
6666
} else {
6767
return sqlite3_create_function_v2(handle, name, 0, 0, 0, 0, 0, 0, 0);
6868
}
@@ -74,7 +74,7 @@ static int _SQLiteCreateCollation(void * context, int len_lhs, const void * lhs,
7474

7575
int SQLiteCreateCollation(sqlite3 * handle, const char * name, SQLiteCreateCollationCallback callback) {
7676
if (callback) {
77-
return sqlite3_create_collation_v2(handle, name, SQLITE_UTF8, (__bridge_retained void *)callback, &_SQLiteCreateCollation, 0); // FIXME: leak
77+
return sqlite3_create_collation_v2(handle, name, SQLITE_UTF8, (__bridge void *)callback, &_SQLiteCreateCollation, 0);
7878
} else {
7979
return sqlite3_create_collation_v2(handle, name, 0, 0, 0, 0);
8080
}

0 commit comments

Comments
 (0)