Сохранить результаты из функции обратного вызова sqlite3_exec в словарь в Swift - PullRequest
0 голосов
/ 04 июня 2019

Я хочу создать функцию, которая выполняет sqlite3_exec и сохраняет результаты в объект словаря, который передается в качестве параметра.Для этого я создал следующий код:

func execute(sql: String, result: inout Dictionary<String, String>) {
    let rc = sqlite3_exec(
        dbPointer,      // database
        sql, // statement
        {        // callback: non-capturing closure
            resultVoidPointer, columnCount, values, columns in

            for i in 0 ..< Int(columnCount) {
                let value = String(cString: values![i]!)
                let column = String(cString: columns![i]!)
                result[column] = value         // Error: Escaping closures can only capture inout parameters explicitly by value
                print("\(column) = \(value)")
            }
            return 0
    },
        nil,
        nil
    )

    if rc != SQLITE_OK {
        print("SQLite Error: " + errorMessage)
    }
}

Но этот код выдает мне следующую ошибку: Escaping closures can only capture inout parameters explicitly by value.Другой попыткой было бы заставить функцию execute возвращать объект словаря, но тогда сообщение об ошибке становится: A C function pointer cannot be formed from a closure that captures context.Как я могу это исправить?

1 Ответ

0 голосов
/ 04 июня 2019

Следуя комментариям Shawn , я создал новую версию execute, в которой я использовал sqlite3_prepare_v2, sqlite3_step и sqlite3_finalize вместо комбинированной функции sqlite3_exec:

func prepare(sql: String) -> OpaquePointer? {
    var statement: OpaquePointer? = nil
    guard sqlite3_prepare_v2(dbPointer, sql, -1, &statement, nil) == SQLITE_OK else {
        print(errorMessage)
        return nil
    }
    return statement
}


func execute(sql: String) -> [Dictionary<String, String>] {
    var result: [Dictionary<String, String>] = []

    guard let queryStatement = prepare(sql: sql) else {
        return result
    }

    defer {
        sqlite3_finalize(queryStatement)
    }

    while sqlite3_step(queryStatement) == SQLITE_ROW {
        var dictionary: Dictionary<String, String> = [:]

        for i in 0...sqlite3_column_count(queryStatement)-1 {
            let column: String = String(cString: sqlite3_column_name(queryStatement, i))
            let value: String = String(cString: sqlite3_column_text(queryStatement, i))
            dictionary[column] = value
        }

        result.append(dictionary)
    }

    guard sqlite3_step(queryStatement) == SQLITE_DONE else {
        print(errorMessage)
        return result
    }

    return result
}

Моя execute функция теперь возвращает массив словарей, где каждый словарь представляет строку для операторов SQL, таких как SELECT. Для других операторов SQL, таких как INSERT, UPDATE или DELETE, где строки не возвращаются, функция execute возвращает пустой массив.

После выполнения оператора SQL к результату можно получить доступ

let result = execute(db, "SELECT id, name, age FROM Table")
print(result[i][age])      // prints the value in row i and column age
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...