From 964a5d465441de9d42b4ae32c6d4b4f6c52610d8 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Wed, 22 Oct 2025 16:37:02 -0700 Subject: [PATCH 1/3] Introduce `SyncMetadata.ID` --- .../SQLiteData/CloudKit/SyncMetadata.swift | 66 ++++- .../CloudKitTests/AccountLifecycleTests.swift | 84 +++--- .../FetchRecordZoneChangesTests.swift | 27 +- .../CloudKitTests/MetadataTests.swift | 121 ++++---- .../CloudKitTests/SharingTests.swift | 261 +++++++++++------- .../SyncEngineDelegateTests.swift | 18 +- .../SyncEngineLifecycleTests.swift | 200 ++++++++------ 7 files changed, 476 insertions(+), 301 deletions(-) diff --git a/Sources/SQLiteData/CloudKit/SyncMetadata.swift b/Sources/SQLiteData/CloudKit/SyncMetadata.swift index 44672565..a1ade417 100644 --- a/Sources/SQLiteData/CloudKit/SyncMetadata.swift +++ b/Sources/SQLiteData/CloudKit/SyncMetadata.swift @@ -11,12 +11,25 @@ /// See for more info. @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) @Table("sqlitedata_icloud_metadata") - public struct SyncMetadata: Hashable, Sendable { + public struct SyncMetadata: Hashable, Identifiable, Sendable { + /// A selection of columns representing a synchronized record's unique identifier and type. + @Selection + public struct ID: Hashable, Sendable { + /// The unique identifier of the record synchronized. + public var recordPrimaryKey: String + + /// The type of the record synchronized, _i.e._ its table name. + public var recordType: String + } + + /// The unique identifier and type of the record synchronized. + public let id: ID + /// The unique identifier of the record synchronized. - public var recordPrimaryKey: String + public var recordPrimaryKey: String { id.recordPrimaryKey } /// The type of the record synchronized, _i.e._ its table name. - public var recordType: String + public var recordType: String { id.recordType } /// The record zone name. public var zoneName: String @@ -35,11 +48,25 @@ @Column(generated: .virtual) public let recordName: String + /// A selection of columns representing a synchronized parent record's unique identifier and + /// type. + @Selection + public struct ParentID: Hashable, Sendable { + /// The unique identifier of the parent record synchronized. + public var parentRecordPrimaryKey: String + + /// The type of the parent record synchronized, _i.e._ its table name. + public var parentRecordType: String + } + + /// The identifier and type of this record's parent, if any. + public var parentRecordID: ParentID? + /// The unique identifier of this record's parent, if any. - public var parentRecordPrimaryKey: String? + public var parentRecordPrimaryKey: String? { parentRecordID?.parentRecordPrimaryKey } /// The type of this record's parent, _i.e._ its table name, if any. - public var parentRecordType: String? + public var parentRecordType: String? { parentRecordID?.parentRecordType } /// The name of this record's parent, if any. /// @@ -85,6 +112,25 @@ public var userModificationTime: Int64 } + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + extension SyncMetadata.TableColumns { + public var recordPrimaryKey: TableColumn { + id.recordPrimaryKey + } + + public var recordType: TableColumn { + id.recordType + } + + public var parentRecordPrimaryKey: TableColumn { + parentRecordID.parentRecordPrimaryKey + } + + public var parentRecordType: TableColumn { + parentRecordID.parentRecordType + } + } + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) extension SyncMetadata { package init( @@ -99,16 +145,18 @@ share: CKShare? = nil, userModificationTime: Int64 ) { - self.recordPrimaryKey = recordPrimaryKey - self.recordType = recordType + self.id = ID(recordPrimaryKey: recordPrimaryKey, recordType: recordType) self.recordName = "\(recordPrimaryKey):\(recordType)" self.zoneName = zoneName self.ownerName = ownerName - self.parentRecordPrimaryKey = parentRecordPrimaryKey - self.parentRecordType = parentRecordType if let parentRecordPrimaryKey, let parentRecordType { + self.parentRecordID = ParentID( + parentRecordPrimaryKey: parentRecordPrimaryKey, + parentRecordType: parentRecordType + ) self.parentRecordName = "\(parentRecordPrimaryKey):\(parentRecordType)" } else { + self.parentRecordID = nil self.parentRecordName = nil } self.lastKnownServerRecord = lastKnownServerRecord diff --git a/Tests/SQLiteDataTests/CloudKitTests/AccountLifecycleTests.swift b/Tests/SQLiteDataTests/CloudKitTests/AccountLifecycleTests.swift index cb85e7c7..a9641ceb 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/AccountLifecycleTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/AccountLifecycleTests.swift @@ -147,13 +147,14 @@ """ ┌────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │ @@ -177,13 +178,17 @@ │ ) │ ├────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: nil, │ │ _lastKnownServerRecordAllFields: nil, │ @@ -228,13 +233,14 @@ """ ┌─────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │ @@ -258,13 +264,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:reminders/zone/__defaultOwner__), │ @@ -382,13 +392,14 @@ """ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner), │ @@ -417,13 +428,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: nil, │ │ _lastKnownServerRecordAllFields: nil, │ @@ -474,13 +489,14 @@ """ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner), │ @@ -509,13 +525,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:reminders/external.zone/external.owner), │ diff --git a/Tests/SQLiteDataTests/CloudKitTests/FetchRecordZoneChangesTests.swift b/Tests/SQLiteDataTests/CloudKitTests/FetchRecordZoneChangesTests.swift index 6e6007af..505930e4 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/FetchRecordZoneChangesTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/FetchRecordZoneChangesTests.swift @@ -522,13 +522,14 @@ """ ┌────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "tag", │ - │ recordType: "tags", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "tag", │ + │ recordType: "tags" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "tag:tags", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(tag:tags/zone/__defaultOwner__), │ @@ -604,13 +605,14 @@ """ ┌────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "tag", │ - │ recordType: "tags", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "tag", │ + │ recordType: "tags" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "tag:tags", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(tag:tags/zone/__defaultOwner__), │ @@ -673,13 +675,14 @@ """ ┌────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "weekend", │ - │ recordType: "tags", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "weekend", │ + │ recordType: "tags" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "weekend:tags", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(weekend:tags/zone/__defaultOwner__), │ diff --git a/Tests/SQLiteDataTests/CloudKitTests/MetadataTests.swift b/Tests/SQLiteDataTests/CloudKitTests/MetadataTests.swift index e8e40745..bace04aa 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/MetadataTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/MetadataTests.swift @@ -209,13 +209,14 @@ """ ┌─────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminderTags", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminderTags" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:reminderTags", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:reminderTags/zone/__defaultOwner__), │ @@ -240,13 +241,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:reminders/zone/__defaultOwner__), │ @@ -272,13 +277,14 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │ @@ -302,13 +308,14 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "2", │ - │ recordType: "reminderTags", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "2", │ + │ recordType: "reminderTags" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "2:reminderTags", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(2:reminderTags/zone/__defaultOwner__), │ @@ -333,13 +340,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "2", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "2", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "2:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(2:reminders/zone/__defaultOwner__), │ @@ -365,13 +376,14 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "2", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "2", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "2:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(2:remindersLists/zone/__defaultOwner__), │ @@ -395,13 +407,14 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "3", │ - │ recordType: "reminderTags", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "3", │ + │ recordType: "reminderTags" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "3:reminderTags", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(3:reminderTags/zone/__defaultOwner__), │ @@ -426,13 +439,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "3", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "3", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "3:reminders", │ - │ parentRecordPrimaryKey: "2", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "2", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "2:remindersLists", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(3:reminders/zone/__defaultOwner__), │ @@ -458,13 +475,14 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "optional", │ - │ recordType: "tags", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "optional", │ + │ recordType: "tags" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "optional:tags", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(optional:tags/zone/__defaultOwner__), │ @@ -487,13 +505,14 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "weekend", │ - │ recordType: "tags", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "weekend", │ + │ recordType: "tags" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "weekend:tags", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(weekend:tags/zone/__defaultOwner__), │ @@ -538,13 +557,14 @@ """ ┌─────────────────────┬────────────────────────────────────────────────────────────────────┐ │ RemindersList( │ SyncMetadata( │ - │ id: 1, │ recordPrimaryKey: "1", │ - │ title: "Personal" │ recordType: "remindersLists", │ - │ ) │ zoneName: "zone", │ + │ id: 1, │ id: SyncMetadata.ID( │ + │ title: "Personal" │ recordPrimaryKey: "1", │ + │ ) │ recordType: "remindersLists" │ + │ │ ), │ + │ │ zoneName: "zone", │ │ │ ownerName: "__defaultOwner__", │ │ │ recordName: "1:remindersLists", │ - │ │ parentRecordPrimaryKey: nil, │ - │ │ parentRecordType: nil, │ + │ │ parentRecordID: nil, │ │ │ parentRecordName: nil, │ │ │ lastKnownServerRecord: CKRecord( │ │ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │ @@ -568,13 +588,14 @@ │ │ ) │ ├─────────────────────┼────────────────────────────────────────────────────────────────────┤ │ RemindersList( │ SyncMetadata( │ - │ id: 2, │ recordPrimaryKey: "2", │ - │ title: "Work" │ recordType: "remindersLists", │ - │ ) │ zoneName: "zone", │ + │ id: 2, │ id: SyncMetadata.ID( │ + │ title: "Work" │ recordPrimaryKey: "2", │ + │ ) │ recordType: "remindersLists" │ + │ │ ), │ + │ │ zoneName: "zone", │ │ │ ownerName: "__defaultOwner__", │ │ │ recordName: "2:remindersLists", │ - │ │ parentRecordPrimaryKey: nil, │ - │ │ parentRecordType: nil, │ + │ │ parentRecordID: nil, │ │ │ parentRecordName: nil, │ │ │ lastKnownServerRecord: CKRecord( │ │ │ recordID: CKRecord.ID(2:remindersLists/zone/__defaultOwner__), │ diff --git a/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift b/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift index 84cf5265..fc03ab5f 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift @@ -316,13 +316,14 @@ """ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner), │ @@ -389,13 +390,14 @@ """ ┌─────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelAs/external.zone/external.owner), │ @@ -419,13 +421,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelBs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelBs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelBs", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "modelAs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "modelAs" │ + │ ), │ │ parentRecordName: "1:modelAs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), │ @@ -450,13 +456,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelCs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelCs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelCs", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "modelBs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "modelBs" │ + │ ), │ │ parentRecordName: "1:modelBs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), │ @@ -926,13 +936,14 @@ """ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner), │ @@ -961,13 +972,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:reminders/external.zone/external.owner), │ @@ -1406,13 +1421,14 @@ """ ┌──────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), │ @@ -1436,13 +1452,14 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "2", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "2", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "2:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), │ @@ -1471,13 +1488,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelBs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelBs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelBs", │ - │ parentRecordPrimaryKey: "2", │ - │ parentRecordType: "modelAs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "2", │ + │ parentRecordType: "modelAs" │ + │ ), │ │ parentRecordName: "2:modelAs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), │ @@ -1502,13 +1523,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelCs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelCs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelCs", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "modelBs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "modelBs" │ + │ ), │ │ parentRecordName: "1:modelBs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), │ @@ -1701,13 +1726,14 @@ """ ┌──────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), │ @@ -1731,13 +1757,14 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "2", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "2", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "2:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), │ @@ -1766,13 +1793,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelBs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelBs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelBs", │ - │ parentRecordPrimaryKey: "2", │ - │ parentRecordType: "modelAs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "2", │ + │ parentRecordType: "modelAs" │ + │ ), │ │ parentRecordName: "2:modelAs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), │ @@ -1797,13 +1828,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelCs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelCs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelCs", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "modelBs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "modelBs" │ + │ ), │ │ parentRecordName: "1:modelBs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), │ @@ -1996,13 +2031,14 @@ """ ┌──────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), │ @@ -2026,13 +2062,14 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "2", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "2", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "2:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), │ @@ -2061,13 +2098,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelBs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelBs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelBs", │ - │ parentRecordPrimaryKey: "2", │ - │ parentRecordType: "modelAs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "2", │ + │ parentRecordType: "modelAs" │ + │ ), │ │ parentRecordName: "2:modelAs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), │ @@ -2092,13 +2133,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelCs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelCs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelCs", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "modelBs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "modelBs" │ + │ ), │ │ parentRecordName: "1:modelBs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), │ @@ -2271,13 +2316,14 @@ """ ┌──────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), │ @@ -2301,13 +2347,14 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "2", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "2", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "2:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), │ @@ -2336,13 +2383,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelBs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelBs" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:modelBs", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "modelAs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "modelAs" │ + │ ), │ │ parentRecordName: "1:modelAs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelBs/zone/__defaultOwner__), │ @@ -2507,13 +2558,14 @@ """ ┌──────────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), │ @@ -2537,13 +2589,14 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "2", │ - │ recordType: "modelAs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "2", │ + │ recordType: "modelAs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "2:modelAs", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), │ @@ -2572,13 +2625,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelBs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelBs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelBs", │ - │ parentRecordPrimaryKey: "2", │ - │ parentRecordType: "modelAs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "2", │ + │ parentRecordType: "modelAs" │ + │ ), │ │ parentRecordName: "2:modelAs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), │ @@ -2603,13 +2660,17 @@ │ ) │ ├──────────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "modelCs", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "modelCs" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:modelCs", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "modelBs", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "modelBs" │ + │ ), │ │ parentRecordName: "1:modelBs", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), │ diff --git a/Tests/SQLiteDataTests/CloudKitTests/SyncEngineDelegateTests.swift b/Tests/SQLiteDataTests/CloudKitTests/SyncEngineDelegateTests.swift index ab73ae16..c97c95ee 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/SyncEngineDelegateTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/SyncEngineDelegateTests.swift @@ -39,13 +39,14 @@ """ ┌────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │ @@ -112,13 +113,14 @@ """ ┌────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │ diff --git a/Tests/SQLiteDataTests/CloudKitTests/SyncEngineLifecycleTests.swift b/Tests/SQLiteDataTests/CloudKitTests/SyncEngineLifecycleTests.swift index 8bea578e..769b0d53 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/SyncEngineLifecycleTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/SyncEngineLifecycleTests.swift @@ -33,43 +33,48 @@ assertQuery(SyncMetadata.all, database: syncEngine.metadatabase) { """ - ┌─────────────────────────────────────────┐ - │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ - │ zoneName: "zone", │ - │ ownerName: "__defaultOwner__", │ - │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ - │ parentRecordName: nil, │ - │ lastKnownServerRecord: nil, │ - │ _lastKnownServerRecordAllFields: nil, │ - │ share: nil, │ - │ _isDeleted: false, │ - │ hasLastKnownServerRecord: false, │ - │ isShared: false, │ - │ userModificationTime: 0 │ - │ ) │ - ├─────────────────────────────────────────┤ - │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ - │ zoneName: "zone", │ - │ ownerName: "__defaultOwner__", │ - │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ - │ parentRecordName: "1:remindersLists", │ - │ lastKnownServerRecord: nil, │ - │ _lastKnownServerRecordAllFields: nil, │ - │ share: nil, │ - │ _isDeleted: false, │ - │ hasLastKnownServerRecord: false, │ - │ isShared: false, │ - │ userModificationTime: 0 │ - │ ) │ - └─────────────────────────────────────────┘ + ┌──────────────────────────────────────────┐ + │ SyncMetadata( │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ + │ zoneName: "zone", │ + │ ownerName: "__defaultOwner__", │ + │ recordName: "1:remindersLists", │ + │ parentRecordID: nil, │ + │ parentRecordName: nil, │ + │ lastKnownServerRecord: nil, │ + │ _lastKnownServerRecordAllFields: nil, │ + │ share: nil, │ + │ _isDeleted: false, │ + │ hasLastKnownServerRecord: false, │ + │ isShared: false, │ + │ userModificationTime: 0 │ + │ ) │ + ├──────────────────────────────────────────┤ + │ SyncMetadata( │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ + │ zoneName: "zone", │ + │ ownerName: "__defaultOwner__", │ + │ recordName: "1:reminders", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ + │ parentRecordName: "1:remindersLists", │ + │ lastKnownServerRecord: nil, │ + │ _lastKnownServerRecordAllFields: nil, │ + │ share: nil, │ + │ _isDeleted: false, │ + │ hasLastKnownServerRecord: false, │ + │ isShared: false, │ + │ userModificationTime: 0 │ + │ ) │ + └──────────────────────────────────────────┘ """ } assertInlineSnapshot(of: container, as: .customDump) { @@ -279,13 +284,14 @@ """ ┌───────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner), │ @@ -310,13 +316,17 @@ │ ) │ ├───────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "external.zone", │ │ ownerName: "external.owner", │ │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: nil, │ │ _lastKnownServerRecordAllFields: nil, │ @@ -498,43 +508,48 @@ assertQuery(SyncMetadata.all, database: syncEngine.metadatabase) { """ - ┌─────────────────────────────────────────┐ - │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ - │ zoneName: "zone", │ - │ ownerName: "__defaultOwner__", │ - │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ - │ parentRecordName: nil, │ - │ lastKnownServerRecord: nil, │ - │ _lastKnownServerRecordAllFields: nil, │ - │ share: nil, │ - │ _isDeleted: false, │ - │ hasLastKnownServerRecord: false, │ - │ isShared: false, │ - │ userModificationTime: 0 │ - │ ) │ - ├─────────────────────────────────────────┤ - │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ - │ zoneName: "zone", │ - │ ownerName: "__defaultOwner__", │ - │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ - │ parentRecordName: "1:remindersLists", │ - │ lastKnownServerRecord: nil, │ - │ _lastKnownServerRecordAllFields: nil, │ - │ share: nil, │ - │ _isDeleted: false, │ - │ hasLastKnownServerRecord: false, │ - │ isShared: false, │ - │ userModificationTime: 0 │ - │ ) │ - └─────────────────────────────────────────┘ + ┌──────────────────────────────────────────┐ + │ SyncMetadata( │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ + │ zoneName: "zone", │ + │ ownerName: "__defaultOwner__", │ + │ recordName: "1:remindersLists", │ + │ parentRecordID: nil, │ + │ parentRecordName: nil, │ + │ lastKnownServerRecord: nil, │ + │ _lastKnownServerRecordAllFields: nil, │ + │ share: nil, │ + │ _isDeleted: false, │ + │ hasLastKnownServerRecord: false, │ + │ isShared: false, │ + │ userModificationTime: 0 │ + │ ) │ + ├──────────────────────────────────────────┤ + │ SyncMetadata( │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ + │ zoneName: "zone", │ + │ ownerName: "__defaultOwner__", │ + │ recordName: "1:reminders", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ + │ parentRecordName: "1:remindersLists", │ + │ lastKnownServerRecord: nil, │ + │ _lastKnownServerRecordAllFields: nil, │ + │ share: nil, │ + │ _isDeleted: false, │ + │ hasLastKnownServerRecord: false, │ + │ isShared: false, │ + │ userModificationTime: 0 │ + │ ) │ + └──────────────────────────────────────────┘ """ } assertInlineSnapshot(of: container, as: .customDump) { @@ -561,13 +576,14 @@ """ ┌─────────────────────────────────────────────────────────────────────────────────────────┐ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "remindersLists", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "remindersLists" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:remindersLists", │ - │ parentRecordPrimaryKey: nil, │ - │ parentRecordType: nil, │ + │ parentRecordID: nil, │ │ parentRecordName: nil, │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │ @@ -591,13 +607,17 @@ │ ) │ ├─────────────────────────────────────────────────────────────────────────────────────────┤ │ SyncMetadata( │ - │ recordPrimaryKey: "1", │ - │ recordType: "reminders", │ + │ id: SyncMetadata.ID( │ + │ recordPrimaryKey: "1", │ + │ recordType: "reminders" │ + │ ), │ │ zoneName: "zone", │ │ ownerName: "__defaultOwner__", │ │ recordName: "1:reminders", │ - │ parentRecordPrimaryKey: "1", │ - │ parentRecordType: "remindersLists", │ + │ parentRecordID: SyncMetadata.ParentID( │ + │ parentRecordPrimaryKey: "1", │ + │ parentRecordType: "remindersLists" │ + │ ), │ │ parentRecordName: "1:remindersLists", │ │ lastKnownServerRecord: CKRecord( │ │ recordID: CKRecord.ID(1:reminders/zone/__defaultOwner__), │ From bd090765f405deb1df8adf3da94dfa0efcc6bc2b Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Wed, 22 Oct 2025 17:43:33 -0700 Subject: [PATCH 2/3] wip --- .../xcshareddata/swiftpm/Package.resolved | 24 ++----------- Examples/Reminders/RemindersLists.swift | 2 +- .../SQLiteData/CloudKit/SyncMetadata.swift | 35 +++++++++++++++---- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6d103b31..a0d54872 100644 --- a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "72bc7483118f950b5981c86ad1ea986d789ceef2694a317cea1b9dfff3119f82", + "originHash" : "c133bf7d10c8ce1e5d6506c3d2f080eac8b4c8c2827044d53a9b925e903564fd", "pins" : [ { "identity" : "combine-schedulers", @@ -73,24 +73,6 @@ "version" : "1.9.4" } }, - { - "identity" : "swift-docc-plugin", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-docc-plugin", - "state" : { - "revision" : "3e4f133a77e644a5812911a0513aeb7288b07d06", - "version" : "1.4.5" - } - }, - { - "identity" : "swift-docc-symbolkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swiftlang/swift-docc-symbolkit", - "state" : { - "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", - "version" : "1.0.0" - } - }, { "identity" : "swift-identified-collections", "kind" : "remoteSourceControl", @@ -141,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-structured-queries", "state" : { - "revision" : "edb84b339542b018477bab1d8e4cca851d5fa93c", - "version" : "0.23.0" + "revision" : "3a95b70a81b7027b8a5117e7dd08188837e5f54e", + "version" : "0.24.0" } }, { diff --git a/Examples/Reminders/RemindersLists.swift b/Examples/Reminders/RemindersLists.swift index 8f3f807d..710aa677 100644 --- a/Examples/Reminders/RemindersLists.swift +++ b/Examples/Reminders/RemindersLists.swift @@ -13,7 +13,7 @@ class RemindersListsModel { .group(by: \.id) .order(by: \.position) .leftJoin(Reminder.all) { $0.id.eq($1.remindersListID) && !$1.isCompleted } - .leftJoin(SyncMetadata.all) { $0.hasMetadata(in: $2) } + .leftJoin(SyncMetadata.all) { $0.syncMetadataID.eq($2.id) } .select { ReminderListState.Columns( remindersCount: $1.id.count(), diff --git a/Sources/SQLiteData/CloudKit/SyncMetadata.swift b/Sources/SQLiteData/CloudKit/SyncMetadata.swift index a1ade417..074839be 100644 --- a/Sources/SQLiteData/CloudKit/SyncMetadata.swift +++ b/Sources/SQLiteData/CloudKit/SyncMetadata.swift @@ -187,7 +187,7 @@ } @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) - extension PrimaryKeyedTable where PrimaryKey: IdentifierStringConvertible { + extension PrimaryKeyedTable where PrimaryKey.QueryOutput: IdentifierStringConvertible { /// A query for finding the metadata associated with a record. /// /// - Parameter primaryKey: The primary key of the record whose metadata to look up. @@ -201,13 +201,15 @@ ) } } - } - @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) - extension PrimaryKeyedTable where PrimaryKey.QueryOutput: IdentifierStringConvertible { - /// Constructs a ``SyncMetadata/RecordName-swift.struct`` for a primary keyed table give an ID. - /// - /// - Parameter id: The ID of the record. + /// An identifier representing any associated synchronization metadata. + public var syncMetadataID: SyncMetadata.ID { + SyncMetadata.ID( + recordPrimaryKey: primaryKey.rawIdentifier, + recordType: Self.tableName + ) + } + package static func recordName(for id: PrimaryKey.QueryOutput) -> String { "\(id.rawIdentifier):\(tableName)" } @@ -227,10 +229,29 @@ /// RemindersList /// .leftJoin(SyncMetadata.all) { $0.hasMetadata.in($1) } /// ``` + @available( + *, + deprecated, + message: """ + Join the 'SyncMetadata' table using 'SyncMetadata.id' and 'Table.syncMetadataID', instead. + """ + ) public func hasMetadata(in metadata: SyncMetadata.TableColumns) -> some QueryExpression { metadata.recordType.eq(QueryValue.tableName) && #sql("\(primaryKey)").eq(metadata.recordPrimaryKey) } + + /// An identifier representing any associated synchronization metadata. + /// + /// This helper can be useful when joining your tables to the ``SyncMetadata`` table: + /// + /// ```swift + /// RemindersList + /// .leftJoin(SyncMetadata.all) { $0.syncMetadataID.eq($1.id) } + /// ``` + public var syncMetadataID: some QueryExpression { + #sql("\(primaryKey), \(bind: QueryValue.tableName)") + } } @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) From 9777ea833045bf8fba13b3e2b71f244801d10017 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Wed, 22 Oct 2025 18:21:06 -0700 Subject: [PATCH 3/3] wip --- Sources/SQLiteData/CloudKit/SyncMetadata.swift | 1 + .../Documentation.docc/Articles/CloudKit.md | 14 +++++++------- .../Documentation.docc/Articles/CloudKitSharing.md | 4 ++-- .../SQLiteData/Documentation.docc/SQLiteData.md | 1 + 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Sources/SQLiteData/CloudKit/SyncMetadata.swift b/Sources/SQLiteData/CloudKit/SyncMetadata.swift index 074839be..1f62fc57 100644 --- a/Sources/SQLiteData/CloudKit/SyncMetadata.swift +++ b/Sources/SQLiteData/CloudKit/SyncMetadata.swift @@ -191,6 +191,7 @@ /// A query for finding the metadata associated with a record. /// /// - Parameter primaryKey: The primary key of the record whose metadata to look up. + @available(*, deprecated, message: "Use 'SyncMetadata.find(record.syncMetadataID)', instead") public static func metadata(for primaryKey: PrimaryKey.QueryOutput) -> Where { SyncMetadata.where { #sql( diff --git a/Sources/SQLiteData/Documentation.docc/Articles/CloudKit.md b/Sources/SQLiteData/Documentation.docc/Articles/CloudKit.md index 6983cc68..e7836d10 100644 --- a/Sources/SQLiteData/Documentation.docc/Articles/CloudKit.md +++ b/Sources/SQLiteData/Documentation.docc/Articles/CloudKit.md @@ -541,8 +541,8 @@ to attach the metadatabase to your database connection. This can be done with th ``GRDB/Database/attachMetadatabase(containerIdentifier:)`` method defined on `Database`. See for more information on how to do this. -With that done you can use the ``StructuredQueriesCore/PrimaryKeyedTable/metadata(for:)`` method -to construct a SQL query for fetching the meta data associated with one of your records. +With that done you can use the ``StructuredQueriesCore/PrimaryKeyedTable/syncMetadataID`` property +to construct a SQL query for fetching the metadata associated with one of your records. For example, if you want to retrieve the `CKRecord` that is associated with a particular row in one of your tables, say a reminder, then you can use ``SyncMetadata/lastKnownServerRecord`` to @@ -550,8 +550,8 @@ retrieve the `CKRecord` and then invoke a CloudKit database function to retrieve ```swift let lastKnownServerRecord = try database.read { db in - try RemindersList - .metadata(for: remindersListID) + try SyncMetadata + .find(remindersList.syncMetadataID) .select(\.lastKnownServerRecord) .fetchOne(db) ?? nil @@ -578,7 +578,7 @@ will give you access to the most current list of participants and permissions fo ```swift let share = try database.read { db in try RemindersList - .metadata(for: remindersListID) + .find(remindersList.syncMetadataID) .select(\.share) .fetchOne(db) } @@ -606,7 +606,7 @@ following: @FetchAll( RemindersList - .leftJoin(SyncMetadata.all) { $0.hasMetadata(in: $1) } + .leftJoin(SyncMetadata.all) { $0.syncMetadataID.eq($1.id) } .select { Row.Columns( remindersList: $0, @@ -617,7 +617,7 @@ following: var rows ``` -Here we have used the ``StructuredQueriesCore/PrimaryKeyedTableDefinition/hasMetadata(in:)`` helper +Here we have used the ``StructuredQueriesCore/PrimaryKeyedTableDefinition/syncMetadataID`` helper that is defined on all primary key tables so that we can join ``SyncMetadata`` to `RemindersList`.