Получение результатов от произвольных операторов SQL с правильной привязкой в ​​SQLite.swift

документация по SQLite.swift говорит о выполнении произвольного SQL:

let stmt = try db.prepare("SELECT id, email FROM users")
for row in stmt {
    for (index, name) in stmt.columnNames.enumerate() {
        print ("\(name)=\(row[index]!)")
        // id: Optional(1), email: Optional("[email protected]")
    }
}

Я хотел получить значения прямо так

let stmt = try db.prepare("SELECT id, email FROM users")
for row in stmt {
    let myInt: Int64 = row[0] // error: Cannot convert value of type 'Binding?' to specified type 'Int64'
    let myString: String = row[1] // error: Cannot convert value of type 'Binding?' to specified type 'String'
}

но индекс строки имеет тип Binding?, и я не могу понять, как преобразовать его в нужный мне тип. Я вижу, что в исходном коде есть метод Statement.bind но я до сих пор не понимаю, как его применять.


person Suragch    schedule 15.08.2016    source источник
comment
Вы пытались использовать Expression? (например, let myInt: Expression<Int64> = ...)   -  person l'L'l    schedule 15.08.2016
comment
@l'L'l, хорошая идея. К сожалению, это дает ту же ошибку (не удается преобразовать Binding? в Expression<Int64>). Я успешно использовал Expression в прошлом, но теперь, когда я пытаюсь заставить работать произвольный SQL (из-за моей проблемы с этим), у меня были большие проблемы.   -  person Suragch    schedule 15.08.2016


Ответы (1)


Вы можете получить правильно типизированные выбранные столбцы из таблицы следующим образом:

// The database.
let db = try Connection(...)

// The table.
let users = Table("users")

// Typed column expressions.
let id = Expression<Int64>("id")
let email = Expression<String>("email")

// The query: "SELECT id, email FROM users"
for user in try db.prepare(users.select(id, email)) {
    let id = user[id]       // Int64
    let mail = user[email]  // String
    print(id, mail)
}

Альтернативой является (необязательно) приведение значений Binding к правильному типу:

let stmt = try db.prepare("SELECT id, email FROM users")
for row in stmt {
    if let id = row[0] as? Int64,
        let mail = row[1] as? String {
        print(id, mail)
    }
}
person Martin R    schedule 15.08.2016
comment
Вторая часть вашего ответа решила мою проблему. Первая часть вашего ответа, безусловно, лучше для стандартного случая (и я делал это раньше), но мне особенно интересно, как это сделать при выполнении произвольного SQL. (Я немного обновил свой вопрос, чтобы отразить это.) Причина, по которой я прибегаю к произвольному SQL, заключается в том, что это еще нерешенная проблема . - person Suragch; 16.08.2016
comment
Есть ли способ связать имена столбцов с помощью Expression при доступе к данным строки после произвольного запроса SQL? Я могу предвидеть появление ошибок в будущем, когда я забуду обновить жестко закодированные индексы столбцов. - person Suragch; 16.08.2016
comment
@Suragch: я сомневаюсь в этом. Это потребует анализа строки запроса. - person Martin R; 18.08.2016