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)
}