2017-04-19 4 views
0

Ich bin eine Funktion zu erstellen versuchen, die Abfragen zu SQLite in Swift 3, aber Ich habe Probleme mit den entweichenden ZeichenSQLite SQLITE_MISUSE Fehler in Swift 3

class SQLiteQueryManager { 

    static func insertNewStore(StoreId: Int64, Name: String, Address: String) -> Bool { 

     let vCommand = "INSERT INTO Store (Id, StoreId, Name, Address) VALUES (\(SQLiteConnectionManager.nextID("Store")),\(StoreId),'\(Name)','\(Address)')" 

     return SQLiteConnectionManager.insertDatabase(vCommand) 
    } 

} 

Das Problem spritzt ins, dass, wenn ich bin versuchen SQLiteConnectionManager.insertDatabase auszuführen Funktion, um die Zeichenfolge, die ich bin zu SQLite Senden sieht wie folgt aus:

INSERT INTO Store (Id, StoreID, Name, Adresse) VALUES (1,1, \ 'Tienda 1 \ ', \' Dirección 1 \ ')

Und SQLite lehnt die Abfrage ab.

Ich habe versucht.replacingOccurrences (of: "\", mit: ""), aber es funktioniert nicht.

Ich habe im DB-Browser die Abfrage getestet und funktioniert

INSERT INTO Store (Id, StoreID, Name, Adresse) VALUES (1,1, 'Tienda 1', 'Dirección 1')

Wie kann ich das entfernen? diese

Meine SQLite-Funktion ist:

static func insertDatabase(_ pCommand: String) -> Bool 
{ 
    var vInsertStatement: OpaquePointer? = nil 

    let vDB: OpaquePointer = SQLiteConnectionManager.openDatabase() 

    var vReturn: Bool 

    if sqlite3_prepare_v2(vDB, pCommand.replacingOccurrences(of: "\\", with: ""), -1, &vInsertStatement, nil) == SQLITE_OK { 
     if sqlite3_step(vInsertStatement) == SQLITE_DONE { 
      print("insertDatabase() correct with statement \(pCommand)") 
      vReturn = true 
     } else { 
      print("insertDatabase() fail with statement \(pCommand)") 
      vReturn = false 
     } 
    } else { 
     print("insertDatabase() pCommand could not be prepared") 
     vReturn = false 
    } 

    sqlite3_finalize(vInsertStatement) 

    sqlite3_close(vDB) 

    return vReturn 
} 

Die Open-Funktion Rückkehr ok so meine Vermutung das entweichende char oder so ähnlich ist.

Es handelt sich hierbei die Druckausgabe der Funktion:

insertDatabase() nicht mit Anweisung INSERT INTO Store (Id, StoreID, Name, Adresse) VALUES (1,1, 'Tienda 1',‘ Dirección 1')

UPDATE 1:

sqlite3_step (vInsertStatement) SQLITE_MISUSE zurückkehrt, aber ich kann den Fehler nicht finden, ist die DB in dem Bündel und der open() s Tattement Arbeit und eine Auswahl, die ich mache, funktioniert, was kann falsch sein?

UPDATE 2:

Dies ist, wie ich öffne de DB und kehrt OK:

private static func openDatabase() -> OpaquePointer { 
    var vDB: OpaquePointer? = nil 
    mDBURL = Bundle.main.url(forResource: "ARDB", withExtension: "db") 
    if let vDBURL = mDBURL{ 
     if sqlite3_open(vDBURL.absoluteString, &vDB) == SQLITE_OK { 
      print("The database is open.") 
     } else { 
      print("Unable to open database in method openDatabase().") 
     } 
     return vDB! 
    } else { 
     return vDB! 
    } 
} 

Dann laufe ich dies die letzte Id zu erhalten und arbeitet:

static func nextID(_ pTableName: String!) -> Int 
{ 
    var vGetIdStatement: OpaquePointer? = nil 

    let vDB: OpaquePointer = SQLiteConnectionManager.openDatabase() 

    let vCommand = String(format: "SELECT Id FROM %@ ORDER BY Id DESC LIMIT 1", pTableName) 

    var vResult: Int32? = 0 

    if sqlite3_prepare_v2(vDB, vCommand, -1, &vGetIdStatement, nil) == SQLITE_OK { 
     if sqlite3_step(vGetIdStatement) == SQLITE_ROW { 
      vResult = sqlite3_column_int(vGetIdStatement, 0) 
      print("nextID() correct with statement \(vCommand)") 
     } else { 
      print("nextID() fail with statement \(vCommand)") 
     } 

    } else { 
     print("nextID() statement could not be prepared") 
    } 

    sqlite3_finalize(vGetIdStatement) 

    sqlite3_close(vDB) 

    var id: Int = 1 
    if (vResult != nil) 
    { 
     id = Int(vResult!) + 1 
    } 

    return id 
} 

Ich habe meine Einfügefunktion zu diesem mit oder ohne cString-Anweisung geändert:

static func insertDatabase(_ pCommand: String) -> Bool 
{ 
    var vInsertStatement: OpaquePointer? = nil 

    let vDB: OpaquePointer = SQLiteConnectionManager.openDatabase() 

    var vReturn: Bool 

    if sqlite3_prepare_v2(vDB, pCommand.cString(using: .utf8), -1, &vInsertStatement, nil) == SQLITE_OK { 
     if sqlite3_step(vInsertStatement) == SQLITE_DONE { 
      print("insertDatabase() correct with statement \(pCommand)") 
      vReturn = true 
     } else { 
      print("insertDatabase() fail with statement \(pCommand) with error: \(sqlite3_step(vInsertStatement)) : \(sqlite3_errmsg(vDB))") 
      vReturn = false 
     } 
    } else { 
     print("insertDatabase() \(pCommand) could not be prepared with error: \(sqlite3_prepare_v2(vDB, pCommand.cString(using: .utf8), -1, &vInsertStatement, nil))") 
     vReturn = false 
    } 

    sqlite3_finalize(vInsertStatement) 

    sqlite3_close(vDB) 

    return vReturn 
} 

Wenn ich die sqlite3_errmsg (VDB) in der Konsole aus erhalte ich diese, die nicht hilft:

▿ Optional> ▿ einige: 0x0000000105347e80 - pointer: 4382293632

Wenn ich print sqlite3_step (vInsertStatement) gibt 21 zurück SQLITE_MISUSE

Jede Hilfe wird geschätzt.

Vielen Dank im Voraus.

+2

Verwenden Sie [binding] (https://sqlite.org/c3ref/bind_blob.html), anstatt die Strings direkt zu interpolieren. Aus Sicherheitsgründen ist es eine gute Übung. –

+0

Ich stimme John Montgomery zu: Sie sollen nichts entgehen. SQLite-Anweisungen können mit Werten gespeist werden, ohne dass ein Entweichen erforderlich ist: das sind "Anweisungsbindungen". Jetzt können Sie auch eine robuste Swift-Bibliothek wie https://github.com/groue/GRDB.swift verwenden: 'try db.execute (" INSERT ... VALUES (?, ...) ", Argumente: [value, ...]) ' –

+0

@ GwendalRoué Hallo sqlite3_step (vInsertStatement) gibt SQLITE_MISUSE zurück, aber ich kann den Fehler nicht finden, die DB ist im Bündel und die open() Anweisung funktioniert und eine Auswahl, die ich mache funktioniert, was kann falsch liegen? –

Antwort

1

Ich habe gerade das Problem gefunden, wir haben keine Erlaubnis, im Hauptpaket zu schreiben.

So müssen Sie zuerst die DB kopieren, hier ist der Code:

private static func copyFromBundle() { 
    let vBundlePath = Bundle.main.path(forResource: "ARDB", ofType: ".db") 
    let vDestPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! 
    let vFileManager = FileManager.default 
    let vFullDestPath = URL(fileURLWithPath: vDestPath).appendingPathComponent("ARDB.db") 
    mDocumentsPath = "" 
    if vFileManager.fileExists(atPath: vFullDestPath.path){ 
     print("Database file exist don´t copy.") 
     mDocumentsPath = vFullDestPath.path 
    } else { 
     if vFileManager.fileExists(atPath: vBundlePath!) { 
      do { 
       try vFileManager.copyItem(atPath: vBundlePath!, toPath: vFullDestPath.path) 
       print("Database file does´t exist copy it.") 
       mDocumentsPath = vFullDestPath.path 
      } catch { 
       print("copyFromBundle() fail with error: ",error) 
      } 
     } 
    } 
} 

Danke für die Hilfe.

Glückliche Kodierung.