2016-11-30 58 views
1

我試圖在Swift中創建一個簡單的sqlite數據庫,但我在嘗試創建表時收到錯誤(特別是SQLITE_ERROR)。Swift Sqlite SQL錯誤

這裏是我的代碼:

 var db :OpaquePointer? 
     let dbPath = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 
      .appendingPathComponent("\(Date.init().timeIntervalSince1970)".replacingOccurrences(of: ".", with: "") + ".db") 
      .absoluteString 

     var returnCode :Int32 = sqlite3_open(dbPath.cString(using: .utf8), &db) 
     if SQLITE_OK != returnCode { 
      preconditionFailure("Failed to open db") 
     } 

     var stmt :OpaquePointer? 
     returnCode = sqlite3_prepare_v2(db, "CREATE TABLE Things (name TEXT)".cString(using: .utf8), -1, &stmt, nil) 
     if SQLITE_OK != returnCode { 
      preconditionFailure("Failed to prepare table creation SQL") 
     } 

SQLite是通過Cocoapod包括在內。我試過在轉換爲C字符串時使用不同的字符串編碼,特別是我嘗試過使用ASCII編碼,而且我也嘗試了對數據庫名稱進行硬編碼。

該錯誤發生在sqlite3_prepare_v2

的錯誤消息是「近\」 \∪{01} \「:語法錯誤」

+1

使用'sqlite3_errmsg()'打印錯誤原因。 - 請注意,您可以將Swift字符串直接傳遞給C函數,例如'sqlite3_open(dbPath,&db)' –

+0

@MartinR錯誤信息是「near \」\ u {01} \「:語法錯誤」 –

+0

http://stackoverflow.com/questions/34135305/nsfilemanager-defaultmanager-fileexistsatpath的副本-returns-false-instead-of-true? - 不要使用'absoluteString'來獲取文件路徑。 –

回答

1

我不是100%肯定爲什麼.cString(using: .utf8)方法 到斯威夫特字符串轉換爲C字符串原因問題。 這可能與 Why does Swift return an unexpected pointer when converting an optional String into an UnsafePointer?(這是 報告爲Swift錯誤)中的問題相同。展開的cString() 明確的結果似乎幫助:

let sql = "CREATE TABLE Things (name TEXT)".cString(using: .utf8)! 
returnCode = sqlite3_prepare_v2(db, sql, -1, &stmt, nil) 

但是你可以直接傳遞一個斯威夫特String C函數期待 一個const char *(比較String value to UnsafePointer<UInt8> function parameter behavior):

var returnCode = sqlite3_open(dbPath, &db) 
// ... 
returnCode = sqlite3_prepare_v2(db, "CREATE TABLE Things (name TEXT)", -1, &stmt, nil) 

,這按預期工作。

補充說明:

  • 使用.pathURL轉換爲文件路徑字符串, 不.absoluteString
  • 如果出現問題,使用sqlite3_errmsg()可以獲取錯誤消息。
  • 刪除不必要的類型註釋,如var returnCode :Int32

全部放在一起:

var db: OpaquePointer? 
let dbPath = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 
    .appendingPathComponent("xxx.db") 
    .path 

var returnCode = sqlite3_open(dbPath, &db) 
if SQLITE_OK != returnCode { 
    let errmsg = String(cString: sqlite3_errmsg(db)) 
    fatalError("Failed to open db: \(errmsg)") 
} 

var stmt: OpaquePointer? 
returnCode = sqlite3_prepare_v2(db, "CREATE TABLE Things (name TEXT)", -1, &stmt, nil) 
if SQLITE_OK != returnCode { 
    let errmsg = String(cString: sqlite3_errmsg(db)) 
    fatalError("Failed to prepare table creation SQL: \(errmsg)") 
}