Skip to content

I wonder if this library could be written even safer. #574

Open
@Evertt

Description

@Evertt

One thing I love about this library is that you don't reference columns by string literals, but instead by variables that hold expressions. Like here:

let name = Expression<String?>("name")
users.insert(name <- "Alice")

And here:

for user in try db.prepare(users) {
    print(user[name])
}

However, these expressions are not necessarily tied to the table that you are using them on. You are just initializing them yourself and then using them on the table. There is no guarantee that the users table actually has a column named "name". One could also easily make a typo when writing the string literal "name".

So I was wondering, what if you made a new struct called Column or something, which has a private initializer, so only the library can initialize it. It would work a bit like this:

guard let name = users.columns["name"] else {
    throw AnError("the name column does not exist")
}

users.insert(name <- "Alice")
let user = users.first!
print(user[name])

You see this way we can at least 90% guarantee that the name column is actually a valid column for the users table. It's still not 100% of course, because a developer could still write the following and the compiler would not complain:

guard let name = users.columns["name"] else {
    throw AnError("the name column does not exist")
}

posts.insert(name <- "Alice") // note the incorrect table

However, I reckon this situation is far less likely than someone making a mistake in the current system.

I'd even want to go one step further and apply the same to tables. So right now you can just initialize a table (let users = Table("users")) and start using it, even if there is no such table in the database. You can make that much safer by doing something like this:

let users: Table

if let existingUsersTable = db.tables["users"] {
    users = existingUsersTable
} else {
    users = db.createTable("users") {
        // haven't thought this part out yet...
    }
}

What do you guys think? Of course this would be quite a big overhaul so this could only be implemented in the next major version if you actually like this change.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions