Hello, here are a few notes about the consequences of the forecoming release of Swift 5 on GRDB. Your comments are welcome.
First, some context. The current GRDB version is 3.6.2. All GRDB 3 versions support all Swift compilers in all modes, from 4.0 (Xcode 9.3) to 4.2 (Xcode 10.1). Due to the constraints of semantic versionning, those compatibilies were never broken since GRDB 3.0.0.
Swift 5 supports three modes (-swift-version flags): 4, 4.2, and 5. It is thus, theorically, able to provide the same level of compatibility.
However, until Xcode 10, Swift was lacking SE-0212, shipped with Swift 4.2.
Without SE-0212, it becomes too difficult to maintain GRDB in the long run:
// Breaks with Swift 5 compiler. Intent is: #if compiler(>= 4.2)
#if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
...
#else
...
#endif
// Warning with Swift 5 compiler in Swift 4 mode:
// > 'Hashable.hashValue' is deprecated as a protocol requirement;
// > conform type 'TableAlias' to 'Hashable' by implementing 'hash(into:)' instead
#if swift(>=4.2)
func hash(into hasher: inout Hasher) { ... }
#else
var hashValue: Int { ... }
#endif
Conclusions
I plan to ship a new major release, GRDB 4, which will only support the Swift 4.2+ modes, and will require Xcode 10+.
This major release will contain other light breaking changes. iOS 8 will no longer be supported. Deprecated methods will be removed. Nothing major expected at this point.
Yet I want to explore @beccadax's ideas around the new String interpolation API, in order to see if it can help writing safe SQL (see those tweets). I don't know yet what will be the consequences of this exploration.
I will greatly appreciate any pull request that brings Swift 5 support for GRDB 3. If this pull request never comes, GRDB 3 will not support Swift 5, and the first GRDB version that supports Swift 5 will be GRDB 4. Please reply below if you are interested.
If you have any concern, question, good ideas about other useful breaking changes, it is time to raise your voice!
Thanks for staying on top of GRDB! So I should be able to link GRDB 4 with an iOS 10 app, assuming I compile with Swift 5? I can confirm that I cannot compile GRDB 3.6.2 using Swift 5/Xcode 10.2b2
SQL Interpolation has been merged in the GRDB-4.0 branch! The feature is fully documented.
As usual, writing documentation generates a virtuous feedback loop on the API. It works great, looks great, and is interestingly more able, sometimes, than annotation-based APIs found in other languages (I think pretty much about the Room persistence library by Google). Look especially at the interaction between the maximumScore() and leaders() requests below. Isn't it beautiful?
struct Player {
var id: Int64
var name: String
var score: Int?
}
extension Player: Decodable, FetchableRecord, TableRecord {
/// Deletes all player with no score
static func deleteAllWithoutScore(_ db: Database) throws {
try db.execute(literal: "DELETE FROM \(self) WHERE \(CodingKeys.score) IS NULL")
}
/// The player with a given id
static func filter(id: Int64) -> SQLRequest<Player> {
return "SELECT * FROM \(self) WHERE \(CodingKeys.id) = \(id)"
}
/// All players with the given ids
static func filter(ids: [Int64]) -> SQLRequest<Player> {
return "SELECT * FROM \(self) WHERE \(CodingKeys.id) IN \(ids)"
}
/// The maximum score
static func maximumScore() -> SQLRequest<Int> {
return "SELECT MAX(\(CodingKeys.score)) FROM \(self)"
}
/// All players whose score is the maximum score
static func leaders() -> SQLRequest<Player> {
return """
SELECT * FROM \(self)
WHERE \(CodingKeys.score) = \(maximumScore())
"""
}
}