Skip to content

Commit

Permalink
Fix bug that causes connection to close before onRow is called
Browse files Browse the repository at this point in the history
  • Loading branch information
dpgao committed Jan 6, 2019
1 parent 8430fdb commit 55355ec
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 23 deletions.
38 changes: 20 additions & 18 deletions Sources/SQLite/Database/SQLiteConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public final class SQLiteConnection: BasicWorker, DatabaseConnection, DatabaseQu
public typealias Database = SQLiteDatabase

/// See `DatabaseConnection`.
public var isClosed: Bool = false
public private(set) var isClosed: Bool = false

/// See `DatabaseConnection`.
public var extend: Extend = [:]
Expand All @@ -46,10 +46,12 @@ public final class SQLiteConnection: BasicWorker, DatabaseConnection, DatabaseQu
internal init(database: SQLiteDatabase, on worker: Worker) throws {
self.database = database
// Make database connection
let options = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX
var handle: OpaquePointer?
guard sqlite3_open_v2(database.storage.path, &handle, options, nil) == SQLITE_OK, let c = handle else {
throw SQLiteError(problem: .error, reason: "Could not open database.", source: .capture())
let options = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX
guard sqlite3_open_v2(database.storage.path, &handle, options, nil) == SQLITE_OK,
let c = handle,
sqlite3_busy_handler(c, { _, _ in 1 }, nil) == SQLITE_OK else {
throw SQLiteError(problem: .error, reason: "Could not open database.", source: .capture())
}
self.handle = c
self.eventLoop = worker.eventLoop
Expand All @@ -66,7 +68,7 @@ public final class SQLiteConnection: BasicWorker, DatabaseConnection, DatabaseQu
}

/// See `SQLConnection`.
public func decode<D>(_ type: D.Type, from row: [SQLiteColumn : SQLiteData], table: GenericSQLTableIdentifier<SQLiteIdentifier>?) throws -> D where D : Decodable {
public func decode<D>(_ type: D.Type, from row: [SQLiteColumn: SQLiteData], table: GenericSQLTableIdentifier<SQLiteIdentifier>?) throws -> D where D : Decodable {
return try SQLiteRowDecoder().decode(D.self, from: row, table: table)
}

Expand All @@ -80,12 +82,14 @@ public final class SQLiteConnection: BasicWorker, DatabaseConnection, DatabaseQu
/// - query: `SQLiteQuery` to execute.
/// - onRow: Callback for handling each row.
/// - returns: A `Future` that signals completion of the query.
public func query(_ query: SQLiteQuery, _ onRow: @escaping ([SQLiteColumn: SQLiteData]) throws -> ()) -> Future<Void> {
public func query(_ query: SQLiteQuery, _ onRow: @escaping ([SQLiteColumn: SQLiteData]) throws -> Void) -> Future<Void> {
var binds: [Encodable] = []
let sql = query.serialize(&binds)
let data = try! binds.map { try SQLiteDataEncoder().encode($0) }
let data = try! binds.map(SQLiteDataEncoder().encode)

// log before anything happens, in case there's an error
logger?.record(query: sql, values: data.map { $0.description })
logger?.record(query: sql, values: data.map(String.init(describing:)))

let promise = eventLoop.newPromise(Void.self)
database.blockingIO.submit { _ in
do {
Expand All @@ -102,24 +106,22 @@ public final class SQLiteConnection: BasicWorker, DatabaseConnection, DatabaseQu
}
}
}
promise.succeed(result: ())
self.eventLoop.execute {
promise.succeed()
}
} catch {
promise.fail(error: error)
self.eventLoop.execute {
promise.fail(error: error)
}
}
}
return promise.futureResult
}

/// See `DatabaseConnection`.
public func close() {
sqlite3_close(handle)
isClosed = true
}

/// Closes the open SQLite handle on deinit.
deinit {
if !isClosed {
close()
if sqlite3_close(handle) == SQLITE_OK {
isClosed = true
}
}
}
7 changes: 2 additions & 5 deletions Sources/SQLite/Database/SQLiteStatement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ internal struct SQLiteStatement {
}
}
}

}

internal func getColumns() throws -> [SQLiteColumn]? {
Expand Down Expand Up @@ -86,14 +85,12 @@ internal struct SQLiteStatement {
default: throw SQLiteError(statusCode: step, connection: connection, source: .capture())
}


var row: [SQLiteColumn: SQLiteData] = [:]

// iterator over column count again and create a field
// for each column. Use the column we have already initialized.
for i in 0..<Int32(columns.count) {
let col = columns[Int(i)]
row[col] = try data(at: i)
for (i, col) in columns.enumerated() {
row[col] = try data(at: Int32(i))
}

// return to event loop
Expand Down

0 comments on commit 55355ec

Please sign in to comment.