do try catch question

I am trying to understand why I get "Use of unresolved identifier 'db'" below. The connection works but I can't see db outside the do{}. Can someone please explain this and how to correct it? I think it is the scope of the variable db?


func openTheDB2() -> String {

    do {
        let db = try Connection("/Users/benniewarren/Desktop/database.sqlite")
    }
    catch {
        print("Failure2")
    }
    let users = Table("users")
    try db.run(users.create { t in     // CREATE TABLE "users" (
        t.column(id, primaryKey: true) //     "id" INTEGER PRIMARY KEY NOT NULL,
        t.column(email, unique: true)  //     "email" TEXT UNIQUE NOT NULL,
        t.column(name)                 //     "name" TEXT
    })                                 // )
    return "Ok2"
}

Yes, that's what the problem is. The scope issue is a bit worse than you think, because your catch block (as written) falls through at the end, and you have no value of "db" to use on line 10.


So, the first thing you have to face is: What value should this function return if you can't create the Connection? Or should it throw an error instead?

A simple way is to declare a var:


func openTheDB2() -> String {

     var db : Connection?     // If that's the appropriate type
    do {
       db = try Connection("/Users/benniewarren/Desktop/database.sqlite")
    }
    catch {
        print("Failure2")
    }
    let users = Table("users")
    if db != nil {
         try db!.run(users.create { t in     // CREATE TABLE "users" (
             t.column(id, primaryKey: true) //     "id" INTEGER PRIMARY KEY NOT NULL,
             t.column(email, unique: true)  //     "email" TEXT UNIQUE NOT NULL,
             t.column(name)                 //     "name" TEXT
         }  )
         return "Ok2"
     } else {
         return "NOk2"
     }
}

I think I am getting a grasp on do try catch with your answer. I have been trying to move line 03 out of the func to use it across multiple func but no luck so far. I tried a struct but that had issues. Not sure if this should be a new topic? The help here has been great.


func openTheDB2() -> String {

    let db : Connection
    
    do {
        db = try Connection("/Users/benniewarren/Desktop/database.sqlite")
    }
    catch {
        return("Connection error")
    }
    let users = Table("users2")
    let id = Expression<Int64>("id")
    let email = Expression<String?>("word")
    let name = Expression<String>("My Home")
    do {
        try db.run(users.create { t in     // CREATE TABLE "users" (
            t.column(id, primaryKey: true) //     "id" INTEGER PRIMARY KEY NOT NULL,
            t.column(email, unique: true)  //     "email" TEXT UNIQUE NOT NULL,
            t.column(name)                 //     "name" TEXT
        })
    }
    catch {
        return("Create error")
    }
    return "No error"
}

Line 3 is not correct.


db must be a var, not a constant.

var db : Connection? // If that's the appropriate type


I declare it as optional, so that it is possible to test for nil if it was not set.

If you do so, you need to unwrap db later with db!

Or you could just declare

var db : Connection

There is little risk here in fact.


Do you use identifiers elsewhere than in this fund ?

let users = Table("users2")

let id = Expression<Int64>("id")

let email = Expression<String?>("word")

let name = Expression<String>("My Home")


In this case, you could declare them as global constants, out of the func.

do try catch question
 
 
Q