Skip to content
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

Eager Loading of HasMany associations #525

Merged
merged 131 commits into from
May 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
cfb1b2f
QueryInterfaceRequest is not a FetchRequest like others: it will pref…
groue Apr 28, 2019
a88f20f
Introduce including(all:)
groue Apr 28, 2019
f6a5279
Use "join" for actual SQL joins, and refactor SQLRelation around "chi…
groue May 4, 2019
9956571
Not all relation children impact parent's count
groue May 4, 2019
331938c
More including(all:)
groue May 4, 2019
1fbe7cf
Type constraint: check Row equality, not subtyping
groue May 4, 2019
2ca2f11
First prefetch and passing tests
groue May 4, 2019
4b82656
More passing prefetch tests
groue May 4, 2019
a743140
AssociationHasManyPrefetchingSQLTests cleanup
groue May 4, 2019
ce782ce
More passing prefetch tests
groue May 4, 2019
73d622a
Don't prefetch when there is no row
groue May 4, 2019
7ef5669
More passing prefetch tests
groue May 4, 2019
d7b4cf3
More passing prefetch tests
groue May 4, 2019
b00271a
AssociationHasManyPrefetchingSQLTests cleanup
groue May 4, 2019
f1522c0
AssociationHasManyPrefetchingSQLTests cleanup
groue May 4, 2019
217b7ee
AssociationHasManyPrefetchingSQLTests cleanup
groue May 4, 2019
91ec3ba
Group prefetched rows
groue May 4, 2019
5fb6c40
Almost ready to use prefetched rows
groue May 4, 2019
8d75989
Cleanup
groue May 4, 2019
623f2ea
First tests for consumption of prefetched rows
groue May 5, 2019
590f6c2
More tests for consumption of prefetched rows
groue May 5, 2019
efe89f0
More tests for consumption of prefetched rows
groue May 5, 2019
90dd8d1
More tests for consumption of prefetched rows
groue May 5, 2019
1dce152
Introduce Row.prefetchTree
groue May 5, 2019
171cdcb
More tests for consumption of prefetched rows
groue May 5, 2019
8f678c9
Failing tests for consumption of prefetched rows
groue May 5, 2019
40b11f9
TODO: light HasManyThrough
groue May 5, 2019
f199dc3
Rubber duck debugging
groue May 5, 2019
b1bcf63
Fix failing tests for consumption of prefetched rows
groue May 5, 2019
5eff775
More tests for consumption of prefetched rows
groue May 5, 2019
814ed0e
Fix failing tests for consumption of prefetched rows
groue May 5, 2019
f6b2c7e
More tests for consumption of prefetched rows
groue May 5, 2019
bd08845
Failing tests for consumption of prefetched rows
groue May 5, 2019
a45065c
Fix failing tests for consumption of prefetched rows
groue May 5, 2019
560676a
More tests for consumption of prefetched rows
groue May 5, 2019
acb7432
TODO
groue May 5, 2019
8786a60
More tests for consumption of prefetched rows
groue May 5, 2019
17e8df2
Tests for consumption of prefetched rows into Decodable records
groue May 5, 2019
c7fed1c
More tests for consumption of prefetched rows into Decodable records
groue May 5, 2019
2634a09
More tests for consumption of prefetched rows into Decodable records
groue May 5, 2019
04ffc71
TODO
groue May 5, 2019
1c47f01
More tests for consumption of prefetched rows into Decodable records
groue May 5, 2019
9fc5cda
Rename PrefetchesTreeView to PrefetchesView
groue May 6, 2019
c0616c6
More tests for consumption of prefetched rows into Decodable records
groue May 6, 2019
a7ea091
Fix SPM
groue May 8, 2019
46b7618
More tests for consumption of prefetched rows into Decodable records
groue May 16, 2019
881bb45
More tests for consumption of prefetched rows into Decodable records
groue May 16, 2019
644064a
More tests for consumption of prefetched rows into Decodable records
groue May 16, 2019
d18c002
Remove Swift 5 migration warning
groue May 16, 2019
f5177a5
Cleanup
groue May 16, 2019
c4be3e5
Split AssociationPrefetchingTests.swift
groue May 16, 2019
67ec70a
Row prefetch subscript
groue May 16, 2019
3337e49
Tests for consumption of prefetched rows into FetchableRecord
groue May 16, 2019
8038a9d
Tests for consumption of prefetched rows into sets
groue May 16, 2019
70b948b
Row subscript accepts any RangeReplaceableCollection
groue May 16, 2019
a6d348f
Failing tests for prefetched rows and equality check
groue May 17, 2019
ae18041
Pass tests for prefetched rows and equality check
groue May 17, 2019
9010153
Failing tests for copied prefetched rows
groue May 17, 2019
c1ed3aa
Better error messages
groue May 17, 2019
ad1bdd7
Rename Row.prefetches to Row.prefetchedRows
groue May 17, 2019
eb977e9
Make Row.PrefetchedView order predictible
groue May 17, 2019
5f36b43
Tests for Row.debugDescription with prefetched rows
groue May 17, 2019
7703741
Cleanup
groue May 17, 2019
f98502a
Association: remove pivot/destination relation ambiguity
groue May 17, 2019
3786482
Add unordered() to OrderedRequest
groue May 17, 2019
604a51b
Cleanup
groue May 17, 2019
d23f4c3
Prevent fetching cursor of prefetched rows with a "Not implemented" f…
groue May 17, 2019
c5ac0ea
Cleanup
groue May 17, 2019
2a85d89
Cleanup
groue May 17, 2019
670bca0
Failing tests for database region of prefetching requests
groue May 17, 2019
27cbe18
Pass tests for database region of prefetching requests
groue May 18, 2019
ebd393f
Cleanuo
groue May 18, 2019
1a368d3
Cleanup
groue May 18, 2019
c95e9fa
Cleanup
groue May 18, 2019
cd53e01
Simplify PrefetchedRowsDecoder
groue May 18, 2019
5113d08
AssociationPrefetchingSQLTests: no need for association keys
groue May 18, 2019
d2c3371
String.pluralized, String.singularized
groue May 18, 2019
cdcaaa4
Irregularity
groue May 18, 2019
98a7f94
Cleanup
groue May 18, 2019
35027a8
Add Rails license
groue May 18, 2019
ca76032
Association name is turned into singularized or pluralized keys
groue May 19, 2019
637c94b
Pluralize/Singularize last word
groue May 19, 2019
52add83
More inflections
groue May 19, 2019
15dd4fc
Inflections Cleanup
groue May 19, 2019
a1b0baa
leaf, foot, hero
groue May 19, 2019
8e2a8fe
More Associations and inflections
groue May 19, 2019
7377335
Tests for non-inflected singular
groue May 19, 2019
ae6a224
Documentation
groue May 19, 2019
fe0198f
Cleanup
groue May 19, 2019
87b7776
Documentation
groue May 19, 2019
4f17444
Cleanup
groue May 19, 2019
09afd2f
Tests for singularization of hasMany relationship
groue May 19, 2019
ada6002
Cleanup
groue May 19, 2019
d594396
Documentation: associations no longer need a convention for database …
groue May 19, 2019
95c7c10
Association documentation
groue May 19, 2019
5b15a88
Fix HasManyThrough row scopes
groue May 19, 2019
5f3b879
Association documentation and tests
groue May 19, 2019
7268085
Association documentation
groue May 19, 2019
40260c2
Association documentation
groue May 19, 2019
8fd4108
Association documentation
groue May 19, 2019
8f3036b
Association documentation
groue May 19, 2019
6af4b18
Association documentation
groue May 19, 2019
a38850a
Association documentation
groue May 19, 2019
507d603
At last
groue May 19, 2019
b29b521
Character.uppercased() and lowercased() come with the Swiift 5 compiller
groue May 20, 2019
76891a3
Association documentation
groue May 20, 2019
64bcbde
Association documentation
groue May 20, 2019
4b565ae
Association documentation
groue May 20, 2019
6255734
Restore the Convention for Database Table Names chapter
groue May 20, 2019
fde53b1
Association documentation
groue May 20, 2019
304fdab
Association documentation
groue May 20, 2019
30839bd
Association documentation
groue May 20, 2019
2c7b3e7
Association documentation
groue May 20, 2019
bab21d4
CHANGELOG
groue May 20, 2019
332f42b
English table names is recommended
groue May 20, 2019
9678041
Association documentation
groue May 20, 2019
7d4306d
Association documentation
groue May 20, 2019
85a8642
Association documentation
groue May 20, 2019
721fd52
Association documentation
groue May 20, 2019
844fb3c
Fix iOS9 test
groue May 20, 2019
940e9c3
Migration Guide: Associations
groue May 20, 2019
1fdd0bc
Migration Guide: fix links
groue May 20, 2019
bc1e74a
Migration Guide: Associations
groue May 20, 2019
403e5ab
Fix SPM tests
groue May 20, 2019
6f6a8e3
Migration Guide: Associations
groue May 20, 2019
69baff3
Remove a hack: merging hasMany and hasManyThrough with include(all:) …
groue May 20, 2019
81476e5
Improve SQLAssociationKey documentation
groue May 20, 2019
c841120
Cleanup
groue May 20, 2019
7674f2f
Association prefetching: add support for composite foreign keys
groue May 20, 2019
6628c09
Documentation
groue May 20, 2019
c19b3ad
Documentation
groue May 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one expection:
- [#510](https://github.com/groue/GRDB.swift/pull/510) by [@charlesmchen-signal](https://github.com/charlesmchen-signal): Expose DatabaseRegion(table:) initializer
- [#515](https://github.com/groue/GRDB.swift/pull/515) by [@alextrob](https://github.com/alextrob): Add "LIMIT 1" to `fetchOne` requests
- [#517](https://github.com/groue/GRDB.swift/pull/517): Support for SQLCipher 4
- [#525](https://github.com/groue/GRDB.swift/pull/525): Eager Loading of HasMany associations

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ The ideas, in alphabetical order:

:bowtie: Public API Challenge :muscle: Hard :fire: Experimental

Associations can be enhanced in several ways. See the "Known Issues" and "Future Directions" chapter of the [Associations Guide](Documentation/AssociationsBasics.md)
Associations can be enhanced in several ways. See the "Known Issues" chapter of the [Associations Guide](Documentation/AssociationsBasics.md)


### CloudKit
Expand Down
657 changes: 401 additions & 256 deletions Documentation/AssociationsBasics.md

Large diffs are not rendered by default.

71 changes: 68 additions & 3 deletions Documentation/GRDB3MigrationGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,64 @@ In GRDB 3, this scheduling used to be named `.queue(_: startImmediately:)`.
The second breaking change is `ValueObservation.extent`, which was removed in GRDB 4. Now all observations last until the observer returned by the `start` method is deallocated.


### Associations

GRDB4 brought a few new [associations] features:

- **Indirect associations** [HasOneThrough] and [HasManyThrough] let you define associations from a record to another through a third one. For example, they let you easily express many-to-many relations such as "a country has many citizens through its passports":

```swift
struct Country: TableRecord, EncodableRecord {
static let passports = hasMany(Passport.self)
// New!
static let citizens = hasMany(Citizen.self, through: passports, using: Passport.citizen)
var citizens: QueryInterfaceRequest<Citizen> {
return request(for: Country.citizens)
}
}

struct Passport: TableRecord {
static let citizen = belongsTo(Citizen.self)
}

struct Citizen: TableRecord {
}

let country: Country = ...
let citizens: [Citizen] = try dbQueue.read { db in
try country.citizens.fetchAll(db)
}
```

![HasManyThroughSchema](https://cdn.rawgit.com/groue/GRDB.swift/master/Documentation/Images/Associations2/HasManyThroughSchema.svg)

- **Eager loading of HasMany associations**: The new `including(all:)` method lets you load arrays or sets of associated records in a single request:

```swift
// All authors with their respective books
let request = Author.including(all: Author.books)

// This request can feed the following record:
struct AuthorInfo: FetchableRecord, Decodable {
var author: Author
var books: [Book] // all associated books
}
let authorInfos: [AuthorInfo] = try AuthorInfo.fetchAll(db, request)
```

See [Joining And Prefetching Associated Records] for more information.

- **Automatic pluralization and singularization** of association identifiers.

GRDB will automatically **pluralize** or **singularize** names in order to help you easily associate records.

For example, the Book and Author records will automatically feed properties named `books`, `author`, or `bookCount` in your decoded records, without any explicit configuration, as long as the names of the backing database tables are "book" and "author".

The GRDB pluralization mechanisms are very powerful, being capable of pluralizing and singularizing both regular and irregular words (it's directly inspired from the battle-tested [Ruby on Rails inflections](https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-pluralize)).

However, this change may have introduced some incompatibilities with GRDB 3 associations. Check [The Structure of a Joined Request] for more information.


### SQLCipher

The integration of GRDB with SQLCipher has changed.
Expand All @@ -70,9 +128,9 @@ The integration of GRDB with SQLCipher has changed.
+import GRDB
```

2. The default SQLCipher version which comes with GRDB 4 is now SQLCipher 4, which is incompatible with SQLCipher 3. See [Encryption] for more details.
2. The default SQLCipher version which comes with GRDB 4 is now SQLCipher 4, which is incompatible with SQLCipher 3. SQLCipher 3 is still supported, though. See [Encryption] for more details.

3. The `cipherPageSize` and `kdfIterations` configuration properties are discontinued. With GRDB 4, run sql pragmas in `prepareDatabase`:
3. The `cipherPageSize` and `kdfIterations` configuration properties are discontinued. With GRDB 4, run sql pragmas in the `prepareDatabase` property of the configuration:

```swift
var configuration = Configuration()
Expand Down Expand Up @@ -108,4 +166,11 @@ do {

[SQL Interpolation]: SQLInterpolation.md
[ValueObservation]: ../README.md#valueobservation
[Encryption]: ../README.md#encryption
[Encryption]: ../README.md#encryption
[HasOneThrough]: AssociationsBasics.md#hasonethrough
[HasManyThrough]: AssociationsBasics.md#hasmanythrough
[PersistableRecord]: ../README.md#persistablerecord-protocol
[associations]: AssociationsBasics.md
[EncodableRecord]: ../README.md#persistablerecord-protocol
[The Structure of a Joined Request]: AssociationsBasics.md#the-structure-of-a-joined-request
[Joining And Prefetching Associated Records]: AssociationsBasics.md#joining-and-prefetching-associated-records
Loading