0

I'm trying to convert several of my apps to use GRDB.swift. Does anybody have or know where I can find a file to get me started? I've read over most of the GRDB docs but I'm not getting it. Below is a sample scenario.

This I was able to convert from SQLite.sift

class Database
{
    static let shared = Database()
    public let databaseConnection: DatabaseQueue?
    
    private init()
    {
        do
        {
            let fileUrl = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("MyDaatbase.sqlite")
            
            // GRDB
            let databaseConnection = try DatabaseQueue(path: fileUrl.path)
            self.databaseConnection = databaseConnection
        } catch {
            databaseConnection = nil
            let nserror = error as NSError
            print("Cannot connect to Database. Error is: \(nserror), \(nserror.userInfo)")
        }
    }
}

Could someone please convert this to GRDB to help me get started?

static func isAnimation() -> Bool
    {
        let theTable = Table("Settings")
        let theColumn = Expression<String>("AnimateNav")
        var theStatus = false
        
        do {
            for theAnswer in try Database.shared.databaseConnection!.prepare(theTable.select(theColumn)) {
                //print(theAnswer[theColumn])
                let theStatusText = (theAnswer[theColumn])
                
                theStatus = theStatusText == "true" ? true : false
            }
        } catch {
            print("Getting the isAnimation Status failed! Error: \(error)")
        }
        return theStatus
    }
Quailcreek
  • 125
  • 2
  • 9

1 Answers1

1

You can use raw SQL:

static func isAnimation() -> Bool {
    var theStatus = false
    do {
        let animateNav = try Database.shared.databaseConnection!.read { db in
            String.fetchOne(db, sql: "SELECT AnimateNav FROM Settings")
        }
        theStatus = animateNav == "true" ? true : false
    } catch {
        print("Getting the isAnimation Status failed! Error: \(error)")
    }
    return theStatus
}

You can also define a Record type for the Settings table, which is the preferred GRDB way:

// Settings.swift
struct Settings: Codable, FetchableRecord, TableRecord {
    var animateNav: String
    // other properties for other columns in the Settings table
    ...
}

// Your file
static func isAnimation() -> Bool {
    var theStatus = false
    do {
        let settings = try Database.shared.databaseConnection!.read { db in
            try Settings.fetchOne(db)
        }
        theStatus = settings?.animateNav == "true" ? true : false
    } catch {
        print("Getting the isAnimation Status failed! Error: \(error)")
    }
    return theStatus
}
Gwendal Roué
  • 3,949
  • 15
  • 34
  • Thank you very much for the reply. I like the second set up using the Struct. Just one thing. LC made me include the full select statement: try Settings.fetchOne(db, sql: "SELECT AnimateNav FROM Settings"). I assume this is correct and you were just in a rush and left that out. – Quailcreek Jan 04 '21 at 23:31
  • Glad you're getting comfortable. The `Settings.fetchOne(db)` (without raw sql) needs the Setting struct to conform to the `TableRecord` protocol, that I forgot to add in the sample code, yes. I have updated it. – Gwendal Roué Jan 05 '21 at 10:30
  • Thanks again. Adding the TableRecord protocol made things much better. So how does Xcode/GRDB know what column to select in the table? Do the names of the items in the struct need to match the column in the table? sql: "SELECT AnimateNav FROM Settings" – Quailcreek Jan 06 '21 at 02:52
  • [TableRecord](https://github.com/groue/GRDB.swift/blob/master/README.md#tablerecord-protocol) uses the name of the type in order to provide a default table name (you can override it), and selects all columns by default (you can override as well). [Codable records](https://github.com/groue/GRDB.swift/blob/master/README.md#codable-records) provides a default `init(row:)` initializer which maps the coding keys generated by the compiler to the database columns. The answers to many questions are written in the documentation. – Gwendal Roué Jan 06 '21 at 08:47