我正在尝试创建一个向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
任何帮助将不胜感激。
提前致谢。
答案 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)
}
}
}
}
感谢您的帮助。
快乐的编码。