LMAssembly // Correctly handle statement pointers.
This commit is contained in:
parent
a66879f7bf
commit
161aa100cc
|
@ -36,9 +36,6 @@ public extension vChewingLM {
|
||||||
// SQLite 連線是否已經建立。
|
// SQLite 連線是否已經建立。
|
||||||
public private(set) static var isSQLDBConnected: Bool = false
|
public private(set) static var isSQLDBConnected: Bool = false
|
||||||
|
|
||||||
// SQLite Statement 專用的記憶體位置。
|
|
||||||
static var ptrStatement: OpaquePointer?
|
|
||||||
|
|
||||||
// 在函式內部用以記錄狀態的開關。
|
// 在函式內部用以記錄狀態的開關。
|
||||||
public var isCassetteEnabled = false
|
public var isCassetteEnabled = false
|
||||||
public var isPhraseReplacementEnabled = false
|
public var isPhraseReplacementEnabled = false
|
||||||
|
@ -63,10 +60,6 @@ public extension vChewingLM {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func disconnectSQLDB() {
|
public static func disconnectSQLDB() {
|
||||||
if Self.ptrStatement != nil {
|
|
||||||
sqlite3_finalize(Self.ptrStatement)
|
|
||||||
Self.ptrStatement = nil
|
|
||||||
}
|
|
||||||
if Self.ptrSQL != nil {
|
if Self.ptrSQL != nil {
|
||||||
sqlite3_close_v2(Self.ptrSQL)
|
sqlite3_close_v2(Self.ptrSQL)
|
||||||
Self.ptrSQL = nil
|
Self.ptrSQL = nil
|
||||||
|
|
|
@ -57,40 +57,43 @@ enum CoreColumn: Int32 {
|
||||||
extension vChewingLM.LMInstantiator {
|
extension vChewingLM.LMInstantiator {
|
||||||
fileprivate static func querySQL(strStmt sqlQuery: String, coreColumn column: CoreColumn, handler: (String) -> Void) {
|
fileprivate static func querySQL(strStmt sqlQuery: String, coreColumn column: CoreColumn, handler: (String) -> Void) {
|
||||||
guard Self.ptrSQL != nil else { return }
|
guard Self.ptrSQL != nil else { return }
|
||||||
defer { sqlite3_finalize(Self.ptrStatement) }
|
performStatementSansResult { ptrStatement in
|
||||||
sqlite3_prepare_v2(Self.ptrSQL, sqlQuery, -1, &Self.ptrStatement, nil)
|
sqlite3_prepare_v2(Self.ptrSQL, sqlQuery, -1, &ptrStatement, nil)
|
||||||
while sqlite3_step(Self.ptrStatement) == SQLITE_ROW {
|
while sqlite3_step(ptrStatement) == SQLITE_ROW {
|
||||||
guard let rawValue = sqlite3_column_text(Self.ptrStatement, column.id) else { continue }
|
guard let rawValue = sqlite3_column_text(ptrStatement, column.id) else { continue }
|
||||||
handler(String(cString: rawValue))
|
handler(String(cString: rawValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate static func hasSQLResult(strStmt sqlQuery: String, coreColumn column: CoreColumn) -> Bool {
|
fileprivate static func hasSQLResult(strStmt sqlQuery: String, coreColumn column: CoreColumn) -> Bool {
|
||||||
guard Self.ptrSQL != nil else { return false }
|
guard Self.ptrSQL != nil else { return false }
|
||||||
defer { sqlite3_finalize(Self.ptrStatement) }
|
return performStatement { ptrStatement in
|
||||||
sqlite3_prepare_v2(Self.ptrSQL, sqlQuery, -1, &Self.ptrStatement, nil)
|
sqlite3_prepare_v2(Self.ptrSQL, sqlQuery, -1, &ptrStatement, nil)
|
||||||
while sqlite3_step(Self.ptrStatement) == SQLITE_ROW {
|
while sqlite3_step(ptrStatement) == SQLITE_ROW {
|
||||||
guard sqlite3_column_text(Self.ptrStatement, column.id) != nil else { continue }
|
guard sqlite3_column_text(ptrStatement, column.id) != nil else { continue }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 获取字根反查资料。
|
/// 获取字根反查资料。
|
||||||
public static func getFactoryReverseLookupData(with kanji: String) -> [String]? {
|
public static func getFactoryReverseLookupData(with kanji: String) -> [String]? {
|
||||||
var results: [String] = []
|
var results: [String] = []
|
||||||
let sqlQuery = "SELECT * FROM DATA_REV WHERE theChar='\(kanji)';"
|
let sqlQuery = "SELECT * FROM DATA_REV WHERE theChar='\(kanji)';"
|
||||||
guard Self.ptrSQL != nil else { return nil }
|
guard Self.ptrSQL != nil else { return nil }
|
||||||
defer { sqlite3_finalize(Self.ptrStatement) }
|
performStatementSansResult { ptrStatement in
|
||||||
sqlite3_prepare_v2(Self.ptrSQL, sqlQuery, -1, &Self.ptrStatement, nil)
|
sqlite3_prepare_v2(Self.ptrSQL, sqlQuery, -1, &ptrStatement, nil)
|
||||||
while sqlite3_step(Self.ptrStatement) == SQLITE_ROW {
|
while sqlite3_step(ptrStatement) == SQLITE_ROW {
|
||||||
guard let rawValue = sqlite3_column_text(Self.ptrStatement, 1) else { continue }
|
guard let rawValue = sqlite3_column_text(ptrStatement, 1) else { continue }
|
||||||
results.append(
|
results.append(
|
||||||
contentsOf: String(cString: rawValue).split(separator: "\t").map { reading in
|
contentsOf: String(cString: rawValue).split(separator: "\t").map { reading in
|
||||||
Self.restorePhonabetFromASCII(reading.description)
|
Self.restorePhonabetFromASCII(reading.description)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return results.isEmpty ? nil : results
|
return results.isEmpty ? nil : results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,11 @@ extension String {
|
||||||
ptrDB != nil && sqlite3_exec(ptrDB, self, nil, nil, nil) == SQLITE_OK
|
ptrDB != nil && sqlite3_exec(ptrDB, self, nil, nil, nil) == SQLITE_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult func runAsSQLPreparedStep(dbPointer ptrDB: inout OpaquePointer?, stmtPtr ptrStmt: inout OpaquePointer?) -> Bool {
|
@discardableResult func runAsSQLPreparedStep(dbPointer ptrDB: inout OpaquePointer?) -> Bool {
|
||||||
guard ptrDB != nil else { return false }
|
guard ptrDB != nil else { return false }
|
||||||
return sqlite3_prepare_v2(ptrDB, self, -1, &ptrStmt, nil) == SQLITE_OK && sqlite3_step(ptrStmt) == SQLITE_DONE
|
return performStatement { ptrStmt in
|
||||||
|
sqlite3_prepare_v2(ptrDB, self, -1, &ptrStmt, nil) == SQLITE_OK && sqlite3_step(ptrStmt) == SQLITE_DONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,3 +62,23 @@ extension Array where Element == String {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Safe APIs for using SQLite Statements.
|
||||||
|
|
||||||
|
func performStatement(_ handler: (inout OpaquePointer?) -> Bool) -> Bool {
|
||||||
|
var ptrStmt: OpaquePointer?
|
||||||
|
defer {
|
||||||
|
sqlite3_finalize(ptrStmt)
|
||||||
|
ptrStmt = nil
|
||||||
|
}
|
||||||
|
return handler(&ptrStmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func performStatementSansResult(_ handler: (inout OpaquePointer?) -> Void) {
|
||||||
|
var ptrStmt: OpaquePointer?
|
||||||
|
defer {
|
||||||
|
sqlite3_finalize(ptrStmt)
|
||||||
|
ptrStmt = nil
|
||||||
|
}
|
||||||
|
handler(&ptrStmt)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue