Swift 3

时间:2017-04-19 17:26:56

标签: sqlite swift3

我正在尝试创建一个向Swift 3中的SQLite注入查询的函数,但是我遇到了转义字符的问题

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)
    }

}

问题在于,当我尝试执行SQLiteConnectionManager.insertDatabase函数时,我发送给SQLite的字符串如下所示:

  

INSERT INTO Store(Id,StoreId,Name,Address)VALUES(1,1,\'Tienda   1 \',\'Dirección1\')

SQLite拒绝查询。

我尝试过.replacingOccurrences(of:“\”,with:“”),但它不起作用。

我已在数据库浏览器中测试了查询并正常工作

  

INSERT INTO Store(Id,StoreId,Name,Address)VALUES(1,1,'Tienda   1','Dirección1')

如何删除\ ??

我的SQLite功能是:

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
}

Open函数返回ok,所以我的猜测是转义字符或类似的东西。

这是函数的打印输出:

  

insertDatabase()失败,语句INSERT INTO Store(Id,StoreId,   姓名,地址)VALUES(1,1,'Tienda 1','Dirección1')

更新1:

sqlite3_step(vInsertStatement)正在返回SQLITE_MISUSE,但我找不到错误,数据库在bundle和open()语句中工作,而且我正在做的选择是什么,可能出错?

更新2:

这是我打开de DB并返回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!
    }
}

然后我运行它来获取最后一个ID并且有效:

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
}

我已经使用或不使用cString语句将插入函数更改为:

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
}

如果我在控制台中打印sqlite3_errmsg(vDB),我觉得这样做无济于事:

  

▿可选> ▿some:0x0000000105347e80        - pointerValue:4382293632

如果我打印sqlite3_step(vInsertStatement)则返回21 SQLITE_MISUSE

任何帮助将不胜感激。

提前致谢。

1 个答案:

答案 0 :(得分:1)

我刚发现问题,我们没有在主要包中写作的许可。

所以你必须先复制数据库,这里是代码:

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)
            }
        }
    }
}

感谢您的帮助。

快乐的编码。