Home > other >  How do i make GRDB ignore a stored variable when fetching from SQLite?
How do i make GRDB ignore a stored variable when fetching from SQLite?

Time:02-02

I have a class that adopts both TableRecord and FetchableRecord. I am taging advantage of the automagic query generation provided by GRDB, and I only provide the table name because it doesn't match the class name. However now i want to add stored properties that are only used at run-time, and i don't want GRDB to try to fetch those autmatically. Can i exclude certain variables from the query?

Here is my code:

class Question: Identifiable, Codable, TableRecord, FetchableRecord {
    static var databaseTableName = "questions"
    
    var id: Int?
    var category: Int?
    var code: String?
    var ...
    var ...
    var ...
    var ...
    var selectedAnswer: Int? // This is only used at run-time and not present in the database.
}

I found this:

static var databaseSelection = [Column("id"), Column("category"), Column("code"), ...]

But that requires me to manually specify all the columns that i want it to fetch. Can i do the opposite, and just exclude one column (selectedAnswer)?

Basically what im looking for is something like this:

static var excludedVariables = ["selectedAnswer"]

I had a read through the documentation and couldn't find anything, but i don't know GRDB so i could have missed something.

CodePudding user response:

I think this is not a specific GRDB question, but more of a Codable question, which is "how to exclude one property from being decoded". So your solution could be to explicitly define the coding keys rather than let Swift synthesize them:

enum CodingKeys: String, CodingKey {
  case id, category, code, ...
}

It still requires you to define all of the columns/properties, but that is always the case with Codable when you want to exclude certain properties.

CodePudding user response:

You do not need to do anything:

  • By default, GRDB selects all columns (SELECT * FROM ...). If there is no column for a non-persisted property, it will just not be fetched (and no invalid column will be inserted in the generated SQL).
  • Optional properties are decoded as nil from columns that do not exist in decoded rows.

For example:

import GRDB

var configuration = Configuration()
configuration.prepareDatabase { db in
    db.trace { print("SQL> \($0)") }
}
let dbQueue = DatabaseQueue(configuration: configuration)

struct Player: Identifiable, Codable, TableRecord, FetchableRecord {
    var id: Int64
    var name: String
    var score: Int
    var ignored: Int? // Has no matching column in the database
}

try dbQueue.write { db in
    try db.create(table: "player") { t in
        t.autoIncrementedPrimaryKey("id")
        t.column("name", .text).notNull()
        t.column("score", .integer).notNull()
    }

    try db.execute(sql: """
        INSERT INTO player (id, name, score) VALUES (NULL, 'Arthur', 100);
        INSERT INTO player (id, name, score) VALUES (NULL, 'Barbara', 1000);
        """)
    
    // SELECT * FROM player
    let players = try Player.fetchAll(db)

    // [Player(id: 1, name: "Arthur", score: 100, ignored: nil),
    //  Player(id: 2, name: "Barbara", score: 1000, ignored: nil)]
    print(players)
}
  •  Tags:  
  • Related