Skip to content

Commit 8874760

Browse files
Support attachMetadatabase in previews (#267)
* Support `attachMetadatabase` in previews Previews can currently crash if an app database is provisioned that attaches a metadatabase. Despite trying to ensure all databases are in-memory to work around an Xcode previews quirk, SQLite still throws a file system error when connecting to an in-memory database with a file URL. This PR attempts to work around the issue by sharing the same database connection in previews. This does require losing the internal `DatabaseMigrator` we currently use for the metadatabase and instead depend on `IF NOT EXISTS` because GRDB only supports a single set of migrations per database (we could maybe scope this change just to previews), but this is probably OK. It also means that the migrator will always detect schema changes for previews since the metadatabase tables will conflict, but this is also probably OK since previews are not long-living. * Revert "Support `attachMetadatabase` in previews" This reverts commit 1734711. * wip * wip * wip * wip --------- Co-authored-by: Brandon Williams <[email protected]>
1 parent 6828f5f commit 8874760

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

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

Sources/SQLiteData/CloudKit/SyncEngine.swift

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,23 @@
311311
.select(\.file)
312312
.fetchOne(db)
313313
if let attachedMetadatabasePath {
314-
let attachedMetadatabaseName = URL(filePath: metadatabase.path).lastPathComponent
315-
let metadatabaseName = URL(filePath: attachedMetadatabasePath).lastPathComponent
316-
if attachedMetadatabaseName != metadatabaseName {
314+
let metadatabaseName =
315+
metadatabase.path.isEmpty
316+
? try URL.metadatabase(
317+
databasePath: "",
318+
containerIdentifier: self.container.containerIdentifier
319+
)
320+
.lastPathComponent
321+
: URL(filePath: metadatabase.path).lastPathComponent
322+
let attachedMetadatabaseName =
323+
URL(string: attachedMetadatabasePath)?.lastPathComponent ?? ""
324+
325+
try URL.metadatabase(
326+
databasePath: attachedMetadatabasePath,
327+
containerIdentifier: self.container.containerIdentifier
328+
)
329+
.lastPathComponent
330+
if metadatabaseName != attachedMetadatabaseName {
317331
throw SchemaError(
318332
reason: .metadatabaseMismatch(
319333
attachedPath: attachedMetadatabasePath,
@@ -1917,6 +1931,7 @@
19171931
databasePath: String,
19181932
containerIdentifier: String?
19191933
) throws -> URL {
1934+
let databasePath = databasePath.isEmpty ? ":memory:" : databasePath
19201935
guard let databaseURL = URL(string: databasePath)
19211936
else {
19221937
struct InvalidDatabasePath: Error {}
@@ -1927,9 +1942,9 @@
19271942
return URL(string: "file:\(String.sqliteDataCloudKitSchemaName)?mode=memory&cache=shared")!
19281943
}
19291944
return
1930-
databaseURL
1931-
.deletingLastPathComponent()
1932-
.appending(component: ".\(databaseURL.deletingPathExtension().lastPathComponent)")
1945+
databaseURL.deletingLastPathComponent().appending(
1946+
component: ".\(databaseURL.deletingPathExtension().lastPathComponent)"
1947+
)
19331948
.appendingPathExtension("metadata\(containerIdentifier.map { "-\($0)" } ?? "").sqlite")
19341949
}
19351950

@@ -2022,12 +2037,16 @@
20222037
databasePath: databasePath,
20232038
containerIdentifier: containerIdentifier
20242039
)
2025-
let path = url.path(percentEncoded: false)
2040+
let path = url.isInMemory ? url.absoluteString : url.path(percentEncoded: false)
20262041
try FileManager.default.createDirectory(
20272042
at: .applicationSupportDirectory,
20282043
withIntermediateDirectories: true
20292044
)
2030-
_ = try DatabasePool(path: path).write { db in
2045+
let database: any DatabaseWriter =
2046+
url.isInMemory
2047+
? try DatabaseQueue(path: path)
2048+
: try DatabasePool(path: path)
2049+
_ = try database.write { db in
20312050
try #sql("SELECT 1").execute(db)
20322051
}
20332052
try #sql(
@@ -2044,7 +2063,6 @@
20442063
package struct SchemaError: LocalizedError {
20452064
package enum Reason {
20462065
case cycleDetected
2047-
case inMemoryDatabase
20482066
case invalidForeignKey(ForeignKey)
20492067
case invalidForeignKeyAction(ForeignKey)
20502068
case invalidTableName(String)

0 commit comments

Comments
 (0)