2

In the SQLite Swift documentation there is reference to getting statement results directly. I have a lot of SQL queries prepared and I don't really want to refactor them. I would sooner use them as they are using db.prepare, as per below.

Statements with results may be iterated over.

let stmt = try db.prepare("SELECT id, email FROM users")
for row in stmt {
    print("id: \(row[0]), email: \(row[1])")
    // id: Optional(1), email: Optional("alice@mac.com")
}

The return values always have the "Optional()" around them. Is there a way we can just get the raw row values back without this?

Mark80
  • 55
  • 1
  • 7

3 Answers3

2

Unwrap the values using ! after the variable as @stephencelis said:

let stmt = try db.prepare("SELECT id, email FROM users")
for row in stmt {
    print("id: \(row[0]!), email: \(row[1]!)")
}
Ahmad
  • 603
  • 1
  • 8
  • 17
1

You may want to use https://github.com/groue/GRDB.swift. It lets you extract optionals or non-optionals, just as you wish:

for row in Row.fetch(db, "SELECT id, email FROM users") {
    let id: Int64 = row.value(atIndex: 0)
    let email: String = row.value(atIndex: 1)
    print(id, email)
}
Gwendal Roué
  • 3,949
  • 15
  • 34
0

The type-safe API lets you declare expressions of non-optional types that, when pulled back from a statement, are not wrapped.

From the README:

let users = Table("users")
let id = Expression<Int64>("id")
let name = Expression<String?>("name")
let email = Expression<String>("email")

try db.run(users.create { t in
    t.column(id, primaryKey: true)
    t.column(name)
    t.column(email, unique: true)
})
// CREATE TABLE "users" (
//     "id" INTEGER PRIMARY KEY NOT NULL,
//     "name" TEXT,
//     "email" TEXT NOT NULL UNIQUE
// )

let insert = users.insert(name <- "Alice", email <- "alice@mac.com")
let rowid = try db.run(insert)
// INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com')

for user in db.prepare(users) {
    println("id: \(user[id]), name: \(user[name]), email: \(user[email])")
    // id: 1, name: Optional("Alice"), email: alice@mac.com
}

Note that both id and email, which are non-optional, are returned as such.

stephencelis
  • 4,954
  • 2
  • 29
  • 22
  • Sorry, this doesn't answer really answer my question. I don't really want type-safe, I want to be able to plug in my SQL directly. I'm fine with all answers output as strings, which is the default for SQLite. – Mark80 Nov 10 '15 at 23:08
  • @Mark80 Because SQLite values are dynamically returned at runtime, there's no way for the non-typesafe version to know what an array of values is going to be, other than optional. You can use Swift's numerous optional-unwrapping techniques, however, to deal with the issue! – stephencelis Nov 11 '15 at 18:43
  • @stephencelis what if query is join? – SPatel Sep 03 '20 at 08:30