sqlite:sqlite3_column_count始终返回0

Ian*_*son 8 sqlite google-analytics-api ios cocoapods

我在iOS项目中使用sqlite.但是sqlite3_column_count总是返回0,即使我确定查询确实返回了一些列(我甚至认为SQL中的SELECT查询不可能有零输出列).奇怪的是,这种行为会改变,具体取决于我链接的库的版本,特别是该库使用的编译时选项.

这些是用于库版本的编译时选项,它不起作用:

COMPILER=clang-8.0.0 (clang-800.2.34)
ENABLE_API_ARMOR
ENABLE_FTS3
ENABLE_FTS3_PARENTHESIS
ENABLE_JSON1
ENABLE_LOCKING_STYLE=1
ENABLE_RTREE
ENABLE_UPDATE_DELETE_LIMIT
HAS_CODEC
HAVE_ISNAN
MAX_MMAP_SIZE=20971520
OMIT_AUTORESET
OMIT_BUILTIN_TEST
OMIT_LOAD_EXTENSION
SYSTEM_MALLOC
THREADSAFE=2
Run Code Online (Sandbox Code Playgroud)

以下是适用版本的标志:

COMPILER=clang-8.0.0
SYSTEM_MALLOC
THREADSAFE=1
Run Code Online (Sandbox Code Playgroud)

什么可能导致这种行为?

更新2016/12/01

这是一个可用于重新创建问题的项目:https://github.com/iannewson/Stackoverflow40895740.git

ViewController.swift包含以下代码:

Test.doDbStuff()
Run Code Online (Sandbox Code Playgroud)

此功能包含以下内容:

public static func doDbStuff() {
    do {

        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")
            .path

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

        var stmt :OpaquePointer?
        returnCode = sqlite3_prepare_v2(db, "CREATE TABLE Things (name TEXT)", -1, &stmt, nil)
        if SQLITE_OK != returnCode {
            preconditionFailure("Failed to prepare table creation SQL")
        }
        returnCode = sqlite3_step(stmt)
        if SQLITE_DONE != returnCode {
            preconditionFailure("Failed to execute tbl creation SQL")
        }
        returnCode = sqlite3_prepare_v2(db, "SELECT name FROM sqlite_master WHERE type ='table'", -1, &stmt, nil)
        if SQLITE_OK != returnCode {
            preconditionFailure("Failed to prepare count SQL")
        }
        returnCode = sqlite3_step(stmt)
        if SQLITE_ROW != returnCode {
            preconditionFailure("Failed to execute count SQL")
        } else {
            let columnCount = sqlite3_column_count(stmt)
            print("columnCount: \(columnCount)")
            let name = String(cString: sqlite3_column_text(stmt, 0))
            //print("Num tables: \(count)")
            print("Table name: \(name)")
        }

    } catch let error {
        preconditionFailure(error.localizedDescription)
    }
}
Run Code Online (Sandbox Code Playgroud)

此函数在所有情况下都可以正常工作,并始终创建表并从sqlite_master中检索其名称而不会出现错误.

ViewController.swift还包含以下代码:

    Database.instance().executeSql("CREATE TABLE IF NOT EXISTS Things (name TEXT)")
    Database.instance().printTableNames()
    Database.instance().withStatementFromSql("SELECT name FROM sqlite_master WHERE type ='table'", callback: {statement in
        while SQLITE_ROW == sqlite3_step(statement) {
            print("Column index: \(sqlite3_column_count(statement))")
            let name = SqlHelper.toString(statement, columnName: "name")
            print("Table: \(name)")
        }
    })
Run Code Online (Sandbox Code Playgroud)

此代码创建一个表,然后尝试从sqlite_master检索其名称.这适用于目前在repo中设置的项目,因此要重现安装Google Analytics pod所需的错误.您可以通过pod 'Google/Analytics'在Podfile中取消注释并运行来完成此操作pod install.现在,当您尝试运行此项目时,第一组代码(Test.doDbStuff())仍然可以正常工作,但使用的第二组代码Database将使用EXC_BAD_ACCESS错误或SQLITE_MISUSE从中返回sqlite3_step.