Skip to content

Association to first or last element in a to-many Association #767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 32 commits into from

Conversation

groue
Copy link
Owner

@groue groue commented Apr 18, 2020

This pull request introduces the first and last properties on to-many associations.

They let you feed, for example, a list of all authors along with their latest book:

// Setup
extension Author {
    static let books = hasMany(Book.self)
}

// Usage
struct AuthorInfo: FetchableRecord, Decodable {
    var author: Author
    var lastBook: Book
}
let infos = try dbQueue.read { db in
    try Author
        .including(required: Author.books.order(Column("year")).last)
        .asRequest(of: AuthorInfo.self)
        .fetchAll(db)
}
for info in infos {
    print("Last book of \(info.author.name) is \(info.lastBook.title)")
}

@groue groue added this to the GRDB 5 milestone Apr 18, 2020
@groue groue force-pushed the dev/hasMany-first branch from 650cf65 to c3d7677 Compare April 18, 2020 14:42
@groue groue force-pushed the dev/hasMany-first branch from b3a068e to e604a10 Compare April 18, 2020 15:11
After failed experiment:

SELECT ...
FROM parent
JOIN (SELECT * FROM child LIMIT 1) child ON child.parentId = child.id

The problem is that the join condition can't go inside the subquery, because SQLite complains about unknown table "parent". And when the join condition is outside the subquery, the LIMIT clause has been applied too early.

So we're still stuck with:

SELECT ...
FROM parent
JOIN child ON child.id = (SELECT id FROM child WHERE child.parentId = child.id LIMIT 1)

For some reason SQLite accepts the reference to the parent table in this case.
@groue
Copy link
Owner Author

groue commented Apr 19, 2020

Question regarding a7b8a73 on the SQLite forums: Subqueries and "no such column" error on references to other tables

groue added a commit that referenced this pull request Apr 25, 2020
… of association cardinality

This is a backport of enhancements brought by the failed pull request #767
@groue
Copy link
Owner Author

groue commented Apr 25, 2020

This pr is not ready yet. The use case is definitely relevant, easy to define and understand, and there exists no straight-forward way to address it with the current apis.

But there are still too many implementation challenges. Basically, we need to define the missing foreign key in some kind of temporary tables. The above link to SQLite forums contain some drafts of SQL queries that provide an acceptable runtime complexity, and offer room for optimization when unique indexes on the sorting columns exist.

The problem I don't feel like solving today is that query interface requests let the user use TableAlias in order to build bridges between the various associations used in a request. Those bridges make it difficult to properly isolate the temporary tables needed for this feature. The chances of generating invalid SQL is high. And it is hard to prevent them with a "not implemented" fatal error (the favorite GRDB way to avoid SQL syntax errors when a feature is not implemented).

So... We'll see later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement needs revisiting This issue was closed but it has unfinished business
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant