Skip to content

Commit ed19230

Browse files
authored
Catalyst fixes (#52)
- Fall back to URL(filePath:directoryHint:) if URL(string:) fails - Use immediate transactions for writes groue/GRDB.swift#1485
1 parent c7466ea commit ed19230

7 files changed

Lines changed: 55 additions & 29 deletions

File tree

Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import PackageDescription
44
let package = Package(
55
name: "SQLite",
66
platforms: [
7-
.macOS(.v13), .iOS(.v16), .tvOS(.v16), .watchOS(.v9),
7+
.macOS(.v13), .macCatalyst(.v16),
8+
.iOS(.v16), .tvOS(.v16), .watchOS(.v9),
89
],
910
products: [
1011
.library(
@@ -19,7 +20,7 @@ let package = Package(
1920
),
2021
.package(
2122
url: "https://github.com/groue/GRDB.swift.git",
22-
from: "6.18.0"
23+
from: "6.24.2"
2324
),
2425
.package(
2526
url: "https://github.com/shareup/precise-iso-8601-date-formatter.git",

Sources/SQLite/SQLiteDatabase.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,14 @@ public final class SQLiteDatabase: DatabaseProtocol, @unchecked Sendable {
2828
path: String,
2929
busyTimeout: TimeInterval = 5
3030
) throws -> SQLiteDatabase {
31-
guard path != ":memory:", let url = URL(string: path)
32-
else { throw SQLiteError.SQLITE_IOERR }
31+
guard path != ":memory:" else {
32+
throw SQLiteError.SQLITE_IOERR
33+
}
34+
35+
let url: URL? = URL(string: path)
36+
?? URL(filePath: path, directoryHint: .notDirectory)
37+
38+
guard let url else { throw SQLiteError.SQLITE_IOERR }
3339

3440
let coordinator = NSFileCoordinator(filePresenter: nil)
3541
var fileCoordinatorError: NSError?
@@ -636,11 +642,20 @@ private extension SQLiteDatabase {
636642

637643
var config = Configuration()
638644
config.journalMode = isInMemory ? .default : .wal
645+
// NOTE: GRDB recommends `defaultTransactionKind` be set
646+
// to `.immediate` in order to prevent `SQLITE_BUSY`
647+
// errors. Using `.immediate` appears to disable
648+
// automatic vacuuming.
649+
//
650+
// https://swiftpackageindex.com/groue/grdb.swift/v6.24.2/documentation/grdb/databasesharing#How-to-limit-the-SQLITEBUSY-error
651+
config.defaultTransactionKind = isInMemory
652+
? .deferred
653+
: .immediate
639654
config.busyMode = .timeout(busyTimeout)
640655
config.observesSuspensionNotifications = true
641656
config.maximumReaderCount = max(
642657
ProcessInfo.processInfo.processorCount,
643-
5
658+
6
644659
)
645660

646661
guard !isInMemory else {

Sources/SQLite/SQLiteValue.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ extension [String: SQLiteValue] {
1717
init?(row: Row?) {
1818
guard let row else { return nil }
1919
var sqliteRow = SQLiteRow()
20-
row.forEach { name, value in
20+
for (name, value) in row {
2121
switch DatabaseValue(value: value)?.storage {
2222
case .none, .null:
2323
sqliteRow[name] = .null

Tests/SQLiteTests/SQLiteDatabaseTests.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ final class SQLiteDatabaseTests: XCTestCase {
1717
database = nil
1818
}
1919

20+
func testSQLiteVersionMeetsMinimumRequirements() throws {
21+
try Sandbox.execute { directory in
22+
let path = directory.appendingPathComponent("test.db").path
23+
let db = try SQLiteDatabase(path: path)
24+
defer { try? db.close() }
25+
let version = try SQLiteVersion(db)
26+
XCTAssert(version.isSupported)
27+
}
28+
}
29+
2030
func testDatabaseIsCreated() throws {
2131
try Sandbox.execute { directory in
2232
let path = directory.appendingPathComponent("test.db").path
@@ -133,7 +143,7 @@ final class SQLiteDatabaseTests: XCTestCase {
133143
try database.execute(raw: _createTableWithBlob)
134144

135145
try database.inTransaction { db in
136-
try (0 ..< 1000).forEach { index in
146+
for index in 0 ..< 1000 {
137147
let args: SQLiteArguments = [
138148
"id": .integer(Int64(index)), "data": .data(_textData),
139149
]
@@ -162,7 +172,7 @@ final class SQLiteDatabaseTests: XCTestCase {
162172
try database.execute(raw: _createTableWithBlob)
163173

164174
try database.inTransaction { db in
165-
try (0 ..< 1000).forEach { index in
175+
for index in 0 ..< 1000 {
166176
let args: SQLiteArguments = [
167177
"id": .integer(Int64(index)), "data": .data(_textData),
168178
]
@@ -191,7 +201,7 @@ final class SQLiteDatabaseTests: XCTestCase {
191201
try database.execute(raw: _createTableWithBlob)
192202

193203
try database.inTransaction { db in
194-
try (0 ..< 1000).forEach { index in
204+
for index in 0 ..< 1000 {
195205
let args: SQLiteArguments = [
196206
"id": .integer(Int64(index)), "data": .data(_textData),
197207
]
@@ -220,7 +230,7 @@ final class SQLiteDatabaseTests: XCTestCase {
220230
try db1.execute(raw: _createTableWithBlob)
221231

222232
try db1.inTransaction { db in
223-
try (0 ..< 1000).forEach { index in
233+
for index in 0 ..< 1000 {
224234
let args: SQLiteArguments = [
225235
"id": .integer(Int64(index)), "data": .data(_textData),
226236
]

Tests/SQLiteTests/SQLitePublisherTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ final class SQLitePublisherTests: XCTestCase {
1616
try database.execute(raw: Person.createTable)
1717
try database.execute(raw: Pet.createTable)
1818

19-
try [_person1, _person2].forEach { person in
19+
for person in [_person1, _person2] {
2020
try database.write(Person.insert, arguments: person.asArguments)
2121
}
2222

23-
try [_pet1, _pet2].forEach { pet in
23+
for pet in [_pet1, _pet2] {
2424
try database.write(Pet.insert, arguments: pet.asArguments)
2525
}
2626
}
@@ -104,7 +104,7 @@ final class SQLitePublisherTests: XCTestCase {
104104
defer { try? db.close() }
105105
try db.execute(raw: Person.createTable)
106106

107-
try [_person1, _person2].forEach { person in
107+
for person in [_person1, _person2] {
108108
try db.write(
109109
Person.insert,
110110
arguments: person.asArguments

Tests/SQLiteTests/SQLiteRow+ExtensionsTests.swift

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
1717
("negative", true),
1818
]
1919

20-
try expected.forEach { key, expectedValue in
20+
for (key, expectedValue) in expected {
2121
XCTAssertEqual(expectedValue, try values.value(for: key))
2222
XCTAssertEqual(
2323
expectedValue,
@@ -37,7 +37,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
3737
("nonempty", "123".data(using: .utf8)!),
3838
]
3939

40-
try expected.forEach { key, expectedValue in
40+
for (key, expectedValue) in expected {
4141
XCTAssertEqual(expectedValue, try values.value(for: key))
4242
XCTAssertEqual(
4343
expectedValue,
@@ -58,7 +58,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
5858
("2001", Date(timeIntervalSinceReferenceDate: 123)),
5959
]
6060

61-
try expected.forEach { key, expectedValue in
61+
for (key, expectedValue) in expected {
6262
XCTAssertEqual(expectedValue, try values.value(for: key))
6363
XCTAssertEqual(
6464
expectedValue,
@@ -80,7 +80,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
8080
("negative", -12_345.12345),
8181
]
8282

83-
try expected.forEach { key, expectedValue in
83+
for (key, expectedValue) in expected {
8484
XCTAssertEqual(expectedValue, try values.value(for: key))
8585
XCTAssertEqual(
8686
expectedValue,
@@ -102,7 +102,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
102102
("negative", -12_345),
103103
]
104104

105-
try expected.forEach { key, expectedValue in
105+
for (key, expectedValue) in expected {
106106
XCTAssertEqual(expectedValue, try values.value(for: key))
107107
XCTAssertEqual(
108108
expectedValue,
@@ -124,7 +124,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
124124
("negative", -12_345),
125125
]
126126

127-
try expected.forEach { key, expectedValue in
127+
for (key, expectedValue) in expected {
128128
XCTAssertEqual(expectedValue, try values.value(for: key))
129129
XCTAssertEqual(
130130
expectedValue,
@@ -144,7 +144,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
144144
("nonempty", "This is not empty"),
145145
]
146146

147-
try expected.forEach { key, expectedValue in
147+
for (key, expectedValue) in expected {
148148
XCTAssertEqual(expectedValue, try values.value(for: key))
149149
XCTAssertEqual(
150150
expectedValue,
@@ -165,7 +165,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
165165
("missing", nil),
166166
]
167167

168-
try expected.forEach { key, expectedValue in
168+
for (key, expectedValue) in expected {
169169
XCTAssertEqual(expectedValue, try values.value(for: key))
170170
XCTAssertEqual(
171171
expectedValue,
@@ -186,7 +186,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
186186
("missing", nil),
187187
]
188188

189-
try expected.forEach { key, expectedValue in
189+
for (key, expectedValue) in expected {
190190
XCTAssertEqual(expectedValue, try values.value(for: key))
191191
XCTAssertEqual(
192192
expectedValue,
@@ -209,7 +209,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
209209
("2001", Date(timeIntervalSinceReferenceDate: 123)),
210210
]
211211

212-
try expected.forEach { key, expectedValue in
212+
for (key, expectedValue) in expected {
213213
XCTAssertEqual(expectedValue, try values.value(for: key))
214214
XCTAssertEqual(
215215
expectedValue,
@@ -230,7 +230,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
230230
("missing", nil),
231231
]
232232

233-
try expected.forEach { key, expectedValue in
233+
for (key, expectedValue) in expected {
234234
XCTAssertEqual(expectedValue, try values.value(for: key))
235235
XCTAssertEqual(
236236
expectedValue,
@@ -251,7 +251,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
251251
("missing", nil),
252252
]
253253

254-
try expected.forEach { key, expectedValue in
254+
for (key, expectedValue) in expected {
255255
XCTAssertEqual(expectedValue, try values.value(for: key))
256256
XCTAssertEqual(
257257
expectedValue,
@@ -272,7 +272,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
272272
("missing", nil),
273273
]
274274

275-
try expected.forEach { key, expectedValue in
275+
for (key, expectedValue) in expected {
276276
XCTAssertEqual(expectedValue, try values.value(for: key))
277277
XCTAssertEqual(
278278
expectedValue,
@@ -293,7 +293,7 @@ final class SQLiteRowExtensionsTests: XCTestCase {
293293
("missing", nil),
294294
]
295295

296-
try expected.forEach { key, expectedValue in
296+
for (key, expectedValue) in expected {
297297
XCTAssertEqual(expectedValue, try values.value(for: key))
298298
XCTAssertEqual(
299299
expectedValue,

0 commit comments

Comments
 (0)