首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQLITE_BUSY应用程序中的iOS错误

SQLITE_BUSY应用程序中的iOS错误
EN

Stack Overflow用户
提问于 2015-06-16 22:12:22
回答 2查看 1.1K关注 0票数 1

我正在编写一个iOS应用程序,允许医生从数据库中选择诊断代码,并向sqlite3数据库中的病人支付账单。主页是一个表单,要求提供病人的姓名和出生日期。在主页上还有一个按钮开始搜索诊断代码(向下钻取身体位置)。

我正在使用一个标签栏和一个账单标签,病人标签,和一个医生标签。用户可以从他们各自的页面中添加病人和医生。除非我已经导航到账单选项卡上的诊断详细页面,否则这将显示他们列表中的病人/医生。

我将数据库连接保存在一个"DatabaseManager“类中,该类打开并关闭设备上的数据库文件。

代码语言:javascript
复制
class DatabaseManager {

var db:COpaquePointer!

init(){

}
/**
*   Checks that the database file is on the device. If not, copies the database file to the device.
*   Connects to the database after file is verified to be in the right spot.
**/
func checkDatabaseFileAndOpen(){
    let theFileManager = NSFileManager.defaultManager()
    let filePath = dataFilePath()
    if theFileManager.fileExistsAtPath(filePath) {
        db = openDBPath(filePath)
    } else {

        let pathToBundledDB = NSBundle.mainBundle().pathForResource("testDML", ofType: "sqlite3")// Copy the file from the Bundle and write it to the Device
        let pathToDevice = dataFilePath()
        var error:NSError?

        if (theFileManager.copyItemAtPath(pathToBundledDB!, toPath:pathToDevice, error: nil)) {
            db = openDBPath(pathToDevice)
        } else {
            println("database failure")
        }
    }
}

/**
*   Gets the path of the database file on the device
**/
func dataFilePath() -> String {
    let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    let documentsDirectory = paths[0] as! NSString
    return documentsDirectory.stringByAppendingPathComponent("testDML.sqlite3") as String
}

/**
*   Makes a connection to the database file located at the provided filePath
**/
func openDBPath(filePath:String) -> COpaquePointer {

    var db:COpaquePointer  = nil
    var result = sqlite3_open(filePath, &db)
    println("openResult: \(result)")
    if result != SQLITE_OK {
        sqlite3_close(db)
        println("Failed To Open Database")
        return nil
    }else {
        return db
    }
}

func closeDB() {
    var closeResult = sqlite3_close_v2(db)
    print("closed result:\(closeResult)")
    if closeResult == SQLITE_OK {
    }
}

每次执行查询时,我都会打开数据库,执行查询,然后关闭数据库。每次运行的查询关闭和打开数据库时,我都会得到SQLITE_OK,但只有在导航到账单选项卡的诊断详细信息页时,才会获得SQLITE_BUSY结果。所有细节页面所做的就是检索诊断代码并更新屏幕上的一些文本。病人和医生的新增职能如下:

代码语言:javascript
复制
func addPatientToDatabase(inputPatient:String, dateOfBirth:String, email:String){

    var (firstName, lastName) = split(inputPatient)

    println(dateOfBirth)
    let query = "INSERT INTO Patient (pID,date_of_birth,f_name,l_name, email) VALUES (NULL, '\(dateOfBirth)', '\(firstName)', '\(lastName!)', '\(email)')"
    var statement:COpaquePointer = nil
    if sqlite3_prepare_v2(db, query, -1, &statement, nil) == SQLITE_OK {
        var sqliteResult = sqlite3_step(statement)
        if sqliteResult == SQLITE_DONE {
            println("Saved \(firstName) \(lastName!)")
        }else {
            println("Add patient failed \(sqliteResult)")
        }
    }
}

func addDoctorToDatabase(inputDoctor:String, email:String) {
    var (firstName, lastName) = split(inputDoctor)

    let query = "INSERT INTO Doctor (dID,f_name,l_name, email) VALUES (NULL,'\(firstName)', '\(lastName!)', '\(email)')"
    var statement:COpaquePointer = nil

    if sqlite3_prepare_v2(db, query, -1, &statement, nil) == SQLITE_OK {
        var sqliteResult = sqlite3_step(statement)
        if sqliteResult == SQLITE_DONE {
            println("Saved \(firstName) \(lastName!)")
        }else {
            println("Add doctor failed for \(firstName) \(lastName!) with error \(sqliteResult)")
        }

    }
}

我认为这不会是一个问题,因为用户不可能同时运行两个查询,而且我已经确保只有一个连接。有人对这里可能发生的事有什么建议吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-16 23:19:28

我相信您忘记了使用sqlite3_finalize()完成准备好的语句,除非您进行了不匹配的打开/关闭调用,或者您从多个线程访问了db连接。根据sqlite准则:

如果数据库连接与未完成的准备语句或未完成的sqlite3_backup对象相关联,则sqlite3_close()将保持数据库连接处于打开状态并返回SQLITE_BUSY。

票数 2
EN

Stack Overflow用户

发布于 2016-04-13 21:31:32

在Swift项目中,除了Mostruash的答案之外,您甚至可能需要使用sqlite3_close_v2()方法。sqllite3_close()方法并不总是返回SQLITE_OK。

如果数据库连接与未完成的准备语句或未完成的sqlite3_backup对象相关联,则sqlite3_close()将保持数据库连接处于打开状态并返回SQLITE_BUSY。如果使用未完成的准备语句和/或未完成的sqlite3_close_v2调用sqlite3_backups (),则数据库连接将成为不可用的“僵尸”,当最后准备的语句完成或最后一个sqlite3_backup完成时,该“僵尸”将自动被释放。sqlite3_close_v2()接口用于与垃圾收集的宿主语言一起使用,在这些语言中,析构函数的调用顺序是任意的。 应用程序应该完成所有准备好的语句,关闭所有BLOB句柄,并在试图关闭对象之前完成与sqlite3对象关联的所有sqlite3对象。如果在数据库连接上调用sqlite3_close_v2(),该连接仍然具有未完成的准备语句、BLOB句柄和/或sqlite3_backup对象,那么它将返回SQLITE_OK,并将资源的取消分配推迟到所有准备好的语句、BLOB句柄和sqlite3_backup对象也被销毁之后。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30879155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档