Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
4 changes: 2 additions & 2 deletions Sources/SQLiteData/CloudKit/SyncEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2005,11 +2005,11 @@
if data == nil {
reportIssue("Asset data not found on disk")
}
return "\(quote: columnName) = \(data?.queryFragment ?? "NULL")"
return "\(quote: columnName) = \(data?.queryFragment ?? #""excluded".\#(quote: columnName)"#)"
} else {
return """
\(quote: columnName) = \
\(record.encryptedValues[columnName]?.queryFragment ?? "NULL")
\(record.encryptedValues[columnName]?.queryFragment ?? #""excluded".\#(quote: columnName)"#)
"""
}
}
Expand Down
42 changes: 42 additions & 0 deletions Tests/SQLiteDataTests/CloudKitTests/SchemaChangeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,48 @@
}
}

/*
* Old schema creates record and synchronizes to iCloud.
* Schema is migrated to add a "NOT NULL" column.
* New sync engine is launched.
=> Sync starts without emitting an error.
*/
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
@Test func addColumn_OldRecordsSyncToNewSchema() async throws {
let remindersList = RemindersList(id: 1, title: "Personal")
try await userDatabase.userWrite { db in
try db.seed {
remindersList
}
}
try await syncEngine.processPendingRecordZoneChanges(scope: .private)

syncEngine.stop()

try await userDatabase.userWrite { db in
try #sql(
"""
ALTER TABLE "remindersLists"
ADD COLUMN "position" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0
"""
)
.execute(db)
}

// NB: Sync engine should start without emitting issue.
_ = try await SyncEngine(
container: syncEngine.container,
userDatabase: syncEngine.userDatabase,
tables: syncEngine.tables
.filter { $0.base != Reminder.self && $0.base != RemindersList.self }
+ [
SynchronizedTable(for: ReminderWithPosition.self),
SynchronizedTable(for: RemindersListWithPosition.self),
],
privateTables: syncEngine.privateTables
)
}

@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
@Test func addAssetToRemindersList() async throws {
let personalList = RemindersList(id: 1, title: "Personal")
Expand Down