diff --git a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 3e56ff26..40994f54 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" : "8b698458b719345f562ad056ad435aa3db5d6e852f96e6ca49566c5d31ffb528",
+ "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",
@@ -123,8 +105,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-sharing",
"state" : {
- "revision" : "aaf605733bd93126d1a3658b4021146d95c94cb6",
- "version" : "2.7.3"
+ "revision" : "3bfc408cc2d0bee2287c174da6b1c76768377818",
+ "version" : "2.7.4"
}
},
{
@@ -154,6 +136,15 @@
"version" : "601.0.1"
}
},
+ {
+ "identity" : "swift-tagged",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/pointfreeco/swift-tagged",
+ "state" : {
+ "revision" : "3907a9438f5b57d317001dc99f3f11b46882272b",
+ "version" : "0.10.0"
+ }
+ },
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
diff --git a/Examples/Reminders/TagsForm.swift b/Examples/Reminders/TagsForm.swift
index 1a60166e..c40b777a 100644
--- a/Examples/Reminders/TagsForm.swift
+++ b/Examples/Reminders/TagsForm.swift
@@ -151,7 +151,7 @@ private struct TagView: View {
} label: {
HStack {
if isSelected {
- Image.init(systemName: "checkmark")
+ Image(systemName: "checkmark")
}
Text(tag.title)
}
diff --git a/Package.swift b/Package.swift
index c1d9d21d..73e0aeeb 100644
--- a/Package.swift
+++ b/Package.swift
@@ -24,7 +24,7 @@ let package = Package(
.trait(
name: "SQLiteDataTagged",
description: "Introduce SQLiteData conformances to the swift-tagged package."
- ),
+ )
],
dependencies: [
.package(url: "https://github.com/apple/swift-collections", from: "1.0.0"),
diff --git a/README.md b/README.md
index 29898d0e..f7a9e89e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# SQLiteData
-A [fast](#Performance), lightweight replacement for SwiftData, powered by SQL and supporting
+A [fast](#Performance), lightweight replacement for SwiftData, powered by SQL and supporting
CloudKit synchronization.
[](https://github.com/pointfreeco/sqlite-data/actions/workflows/ci.yml)
@@ -353,8 +353,8 @@ SQLiteData. Check out [this](./Examples) directory to see them all, including:
* [**CloudKitDemo**](./Examples/CloudKitDemo)
A simplified demo that shows how to synchronize a SQLite database to CloudKit and how to
share records with other iCloud users. See our dedicated articles on [CloudKit Synchronization]
- and [CloudKit Sharing] for more information.
-
+ and [CloudKit Sharing] for more information.
+
[CloudKit Synchronization]: https://swiftpackageindex.com/pointfreeco/sqlite-data/main/documentation/sqlitedata/cloudkit
[CloudKit Sharing]: https://swiftpackageindex.com/pointfreeco/sqlite-data/main/documentation/sqlitedata/cloudkitsharing
diff --git a/Sources/SQLiteData/CloudKit/CloudKitSharing.swift b/Sources/SQLiteData/CloudKit/CloudKitSharing.swift
index eac7c4a3..1e2d25ec 100644
--- a/Sources/SQLiteData/CloudKit/CloudKitSharing.swift
+++ b/Sources/SQLiteData/CloudKit/CloudKitSharing.swift
@@ -126,7 +126,7 @@
}
let rootRecord =
- lastKnownServerRecord
+ lastKnownServerRecord
?? CKRecord(
recordType: recordType,
recordID: CKRecord.ID(recordName: recordName, zoneID: defaultZone.zoneID)
@@ -292,7 +292,7 @@
public func cloudSharingControllerDidStopSharing(_ csc: UICloudSharingController) {
Task {
await withErrorReporting(.sqliteDataCloudKitFailure) {
- try await syncEngine.deleteShare(recordID: share.recordID)
+ try await syncEngine.deleteShare(shareRecordID: share.recordID)
}
}
didStopSharing()
diff --git a/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift b/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift
index f6647277..d7198cb2 100644
--- a/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift
+++ b/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift
@@ -141,7 +141,7 @@
assert(
!hasSchemaChanges,
"""
- A previously run migration has been removed or edited.
+ A previously run migration has been removed or edited. \
Metadatabase migrations must not be modified after release.
"""
)
diff --git a/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift b/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift
index 4b75e98c..faea3f1b 100644
--- a/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift
+++ b/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift
@@ -105,7 +105,7 @@ package final class MockCloudContainer: CloudContainer, CustomDumpReflectable {
}
package var customDumpMirror: Mirror {
- Mirror.init(
+ Mirror(
self,
children: [
("privateCloudDatabase", privateCloudDatabase),
diff --git a/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift b/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift
index 4b7fad3a..1eca4a4d 100644
--- a/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift
+++ b/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift
@@ -58,7 +58,8 @@ package final class MockSyncEngine: SyncEngineProtocol {
package func sendChanges(_ options: CKSyncEngine.SendChangesOptions) async throws {
guard
- !parentSyncEngine.syncEngine(for: database.databaseScope).state.pendingRecordZoneChanges.isEmpty
+ !parentSyncEngine.syncEngine(for: database.databaseScope).state.pendingRecordZoneChanges
+ .isEmpty
else { return }
try await parentSyncEngine.processPendingRecordZoneChanges(scope: database.databaseScope)
}
diff --git a/Sources/SQLiteData/CloudKit/Internal/Triggers.swift b/Sources/SQLiteData/CloudKit/Internal/Triggers.swift
index 24ec4200..16077e14 100644
--- a/Sources/SQLiteData/CloudKit/Internal/Triggers.swift
+++ b/Sources/SQLiteData/CloudKit/Internal/Triggers.swift
@@ -55,7 +55,7 @@
parentForeignKey: parentForeignKey,
defaultZone: defaultZone
)
- SyncMetadata.upsert(
+ SyncMetadata.insert(
new: new,
parentForeignKey: parentForeignKey,
defaultZone: defaultZone
@@ -77,7 +77,12 @@
parentForeignKey: parentForeignKey,
defaultZone: defaultZone
)
- SyncMetadata.upsert(
+ SyncMetadata.insert(
+ new: new,
+ parentForeignKey: parentForeignKey,
+ defaultZone: defaultZone
+ )
+ SyncMetadata.update(
new: new,
parentForeignKey: parentForeignKey,
defaultZone: defaultZone
@@ -133,7 +138,7 @@
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
extension SyncMetadata {
- fileprivate static func upsert(
+ fileprivate static func insert(
new: StructuredQueriesCore.TableAlias.TableColumns,
parentForeignKey: ForeignKey?,
defaultZone: CKRecordZone
@@ -143,6 +148,14 @@
parentForeignKey: parentForeignKey,
defaultZone: defaultZone
)
+ let defaultZoneName = #sql(
+ "\(quote: defaultZone.zoneID.zoneName, delimiter: .text)",
+ as: String.self
+ )
+ let defaultOwnerName = #sql(
+ "\(quote: defaultZone.zoneID.ownerName, delimiter: .text)",
+ as: String.self
+ )
return insert {
(
$0.recordPrimaryKey,
@@ -156,17 +169,35 @@
Values(
#sql("\(new.primaryKey)"),
T.tableName,
- zoneName,
- ownerName,
+ zoneName ?? defaultZoneName,
+ ownerName ?? defaultOwnerName,
parentRecordPrimaryKey,
parentRecordType
)
- } onConflict: {
- ($0.recordPrimaryKey, $0.recordType)
- } doUpdate: {
- $0.parentRecordPrimaryKey = $1.parentRecordPrimaryKey
- $0.parentRecordType = $1.parentRecordType
- $0.userModificationTime = $1.userModificationTime
+ } onConflictDoUpdate: { _ in
+ }
+ }
+
+ fileprivate static func update(
+ new: StructuredQueriesCore.TableAlias.TableColumns,
+ parentForeignKey: ForeignKey?,
+ defaultZone: CKRecordZone
+ ) -> some StructuredQueriesCore.Statement {
+ let (parentRecordPrimaryKey, parentRecordType, zoneName, ownerName) = parentFields(
+ alias: new,
+ parentForeignKey: parentForeignKey,
+ defaultZone: defaultZone
+ )
+ return Self.where {
+ $0.recordPrimaryKey.eq(#sql("\(new.primaryKey)"))
+ && $0.recordType.eq(T.tableName)
+ }
+ .update {
+ $0.zoneName = zoneName ?? $0.zoneName
+ $0.ownerName = ownerName ?? $0.ownerName
+ $0.parentRecordPrimaryKey = parentRecordPrimaryKey
+ $0.parentRecordType = parentRecordType
+ $0.userModificationTime = $currentTime()
}
}
}
@@ -176,31 +207,27 @@
static func callbackTriggers(for syncEngine: SyncEngine) -> [TemporaryTrigger] {
[
afterInsertTrigger(for: syncEngine),
+ afterZoneUpdateTrigger(),
afterUpdateTrigger(for: syncEngine),
afterSoftDeleteTrigger(for: syncEngine),
]
}
- private enum ParentSyncMetadata: AliasName {}
-
fileprivate static func afterInsertTrigger(for syncEngine: SyncEngine) -> TemporaryTrigger
{
createTemporaryTrigger(
- "after_insert_on_sqlitedata_icloud_metadata",
+ "\(String.sqliteDataCloudKitSchemaName)_after_insert_on_sqlitedata_icloud_metadata",
ifNotExists: true,
after: .insert { new in
validate(recordName: new.recordName)
Values(
syncEngine.$didUpdate(
recordName: new.recordName,
- lastKnownServerRecord: new.lastKnownServerRecord
- ?? rootServerRecord(recordName: new.recordName),
- newParentLastKnownServerRecord: parentLastKnownServerRecordIfShared(
- parentRecordPrimaryKey: new.parentRecordPrimaryKey,
- parentRecordType: new.parentRecordType
- ),
- parentRecordPrimaryKey: new.parentRecordPrimaryKey,
- parentRecordType: new.parentRecordType
+ zoneName: new.zoneName,
+ ownerName: new.ownerName,
+ oldZoneName: new.zoneName,
+ oldOwnerName: new.ownerName,
+ descendantRecordNames: #bind(nil)
)
)
} when: { _ in
@@ -209,24 +236,58 @@
)
}
+ fileprivate static func afterZoneUpdateTrigger() -> TemporaryTrigger {
+ createTemporaryTrigger(
+ "\(String.sqliteDataCloudKitSchemaName)_after_zone_update_on_sqlitedata_icloud_metadata",
+ ifNotExists: true,
+ after: .update {
+ ($0.zoneName, $0.ownerName)
+ } forEachRow: { old, new in
+ let selfAndDescendantRecordNames = descendantRecordNames(
+ recordName: new.recordName,
+ includeSelf: true
+ ) {
+ $0.select(\.recordName)
+ }
+ SyncMetadata
+ .where {
+ $0.recordName.in(selfAndDescendantRecordNames)
+ }
+ .update {
+ $0.zoneName = new.zoneName
+ $0.ownerName = new.ownerName
+ $0.lastKnownServerRecord = nil
+ $0._lastKnownServerRecordAllFields = nil
+ }
+ } when: { old, new in
+ new.zoneName.neq(old.zoneName) || new.ownerName.neq(old.ownerName)
+ }
+ )
+ }
+
fileprivate static func afterUpdateTrigger(for syncEngine: SyncEngine) -> TemporaryTrigger
{
createTemporaryTrigger(
- "after_update_on_sqlitedata_icloud_metadata",
+ "\(String.sqliteDataCloudKitSchemaName)_after_update_on_sqlitedata_icloud_metadata",
ifNotExists: true,
- after: .update { _, new in
+ after: .update { old, new in
+ let zoneChanged = new.zoneName.neq(old.zoneName) || new.ownerName.neq(old.ownerName)
+ let descendantRecordNamesJSON = descendantRecordNames(
+ recordName: new.recordName,
+ includeSelf: false
+ ) {
+ $0.select { $0.recordName.jsonGroupArray() }
+ }
+
validate(recordName: new.recordName)
Values(
syncEngine.$didUpdate(
recordName: new.recordName,
- lastKnownServerRecord: new.lastKnownServerRecord
- ?? rootServerRecord(recordName: new.recordName),
- newParentLastKnownServerRecord: parentLastKnownServerRecordIfShared(
- parentRecordPrimaryKey: new.parentRecordPrimaryKey,
- parentRecordType: new.parentRecordType
- ),
- parentRecordPrimaryKey: new.parentRecordPrimaryKey,
- parentRecordType: new.parentRecordType
+ zoneName: new.zoneName,
+ ownerName: new.ownerName,
+ oldZoneName: old.zoneName,
+ oldOwnerName: old.ownerName,
+ descendantRecordNames: Case().when(zoneChanged, then: descendantRecordNamesJSON)
)
)
} when: { old, new in
@@ -235,11 +296,11 @@
)
}
- fileprivate static func afterSoftDeleteTrigger(for syncEngine: SyncEngine) -> TemporaryTrigger<
- Self
- > {
+ fileprivate static func afterSoftDeleteTrigger(
+ for syncEngine: SyncEngine
+ ) -> TemporaryTrigger {
createTemporaryTrigger(
- "after_delete_on_sqlitedata_icloud_metadata",
+ "\(String.sqliteDataCloudKitSchemaName)_after_delete_on_sqlitedata_icloud_metadata",
ifNotExists: true,
after: .update(of: \._isDeleted) { _, new in
Values(
@@ -265,17 +326,9 @@
) -> (
parentRecordPrimaryKey: SQLQueryExpression?,
parentRecordType: SQLQueryExpression?,
- zoneName: SQLQueryExpression,
- ownerName: SQLQueryExpression
+ zoneName: SQLQueryExpression,
+ ownerName: SQLQueryExpression
) {
- let zoneName = #sql(
- "\(quote: defaultZone.zoneID.zoneName, delimiter: .text)",
- as: String.self
- )
- let ownerName = #sql(
- "\(quote: defaultZone.zoneID.ownerName, delimiter: .text)",
- as: String.self
- )
return
parentForeignKey
.map { foreignKey in
@@ -284,20 +337,23 @@
as: String.self
)
let parentRecordType = #sql("\(bind: foreignKey.table)", as: String.self)
- let parentMetadata =
- SyncMetadata
- .where {
- $0.recordPrimaryKey.eq(parentRecordPrimaryKey)
- && $0.recordType.eq(parentRecordType)
- }
+ let parentMetadata = SyncMetadata.where {
+ $0.recordPrimaryKey.eq(parentRecordPrimaryKey)
+ && $0.recordType.eq(parentRecordType)
+ }
return (
parentRecordPrimaryKey,
parentRecordType,
- #sql("coalesce((\(parentMetadata.select(\.zoneName))), \(zoneName))"),
- #sql("coalesce((\(parentMetadata.select(\.ownerName))), \(ownerName))")
+ #sql("coalesce(\($currentZoneName()), (\(parentMetadata.select(\.zoneName))))"),
+ #sql("coalesce(\($currentOwnerName()), (\(parentMetadata.select(\.ownerName))))")
)
}
- ?? (nil, nil, zoneName, ownerName)
+ ?? (
+ nil,
+ nil,
+ SQLQueryExpression($currentZoneName()),
+ SQLQueryExpression($currentOwnerName())
+ )
}
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
@@ -356,6 +412,40 @@
}
}
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ private func descendantRecordNames(
+ recordName: some QueryExpression,
+ includeSelf: Bool,
+ select: (Where) -> Select
+ ) -> some Statement {
+ With {
+ SyncMetadata
+ .where { $0.recordName.eq(recordName) }
+ .select {
+ DescendantMetadata.Columns(recordName: $0.recordName, parentRecordName: #bind(nil))
+ }
+ .union(
+ all: true,
+ SyncMetadata
+ .select {
+ DescendantMetadata.Columns(
+ recordName: $0.recordName,
+ parentRecordName: $0.parentRecordName
+ )
+ }
+ .join(DescendantMetadata.all) { $0.parentRecordName.eq($1.recordName) }
+ )
+ } query: {
+ select(
+ DescendantMetadata.where {
+ if !includeSelf {
+ $0.recordName.neq(recordName)
+ }
+ }
+ )
+ }
+ }
+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
private func rootServerRecord(
recordName: some QueryExpression
@@ -378,7 +468,7 @@
}
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
- private func parentLastKnownServerRecordIfShared(
+ private func parentLastKnownServerRecord(
parentRecordPrimaryKey: some QueryExpression,
parentRecordType: some QueryExpression
) -> some QueryExpression {
@@ -406,4 +496,39 @@
substr(1, 1).neq("_") && octetLength().lte(255) && octetLength().eq(length())
}
}
+
+ @Table @Selection
+ private struct DescendantMetadata {
+ let recordName: String
+ let parentRecordName: String?
+ }
+
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ @Table @Selection
+ private struct AncestorMetadata {
+ let recordName: String
+ let parentRecordName: String?
+ @Column(as: CKRecord?.SystemFieldsRepresentation.self)
+ let lastKnownServerRecord: CKRecord?
+ }
+
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ @Table @Selection
+ struct RecordWithRoot {
+ let parentRecordName: String?
+ let recordName: String
+ @Column(as: CKRecord?.SystemFieldsRepresentation.self)
+ let lastKnownServerRecord: CKRecord?
+ let rootRecordName: String
+ @Column(as: CKRecord?.SystemFieldsRepresentation.self)
+ let rootLastKnownServerRecord: CKRecord?
+ }
+
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ @Table @Selection
+ private struct RootShare {
+ let parentRecordName: String?
+ @Column(as: CKShare?.SystemFieldsRepresentation.self)
+ let share: CKShare?
+ }
#endif
diff --git a/Sources/SQLiteData/CloudKit/SyncEngine.swift b/Sources/SQLiteData/CloudKit/SyncEngine.swift
index c4f77e96..cc101c2a 100644
--- a/Sources/SQLiteData/CloudKit/SyncEngine.swift
+++ b/Sources/SQLiteData/CloudKit/SyncEngine.swift
@@ -330,6 +330,8 @@
db.add(function: $didUpdate)
db.add(function: $didDelete)
db.add(function: $hasPermission)
+ db.add(function: $currentZoneName)
+ db.add(function: $currentOwnerName)
for trigger in SyncMetadata.callbackTriggers(for: self) {
try trigger.execute(db)
@@ -571,11 +573,6 @@
for trigger in SyncMetadata.callbackTriggers(for: self).reversed() {
try trigger.drop().execute(db)
}
- db.remove(function: $hasPermission)
- db.remove(function: $didDelete)
- db.remove(function: $didUpdate)
- db.remove(function: $syncEngineIsSynchronizingChanges)
- db.remove(function: $currentTime)
}
try metadatabase.erase()
try migrate(metadatabase: metadatabase)
@@ -604,62 +601,71 @@
"sqlitedata_icloud_didUpdate",
as: ((
String,
- CKRecord?.SystemFieldsRepresentation,
- CKRecord?.SystemFieldsRepresentation,
- String?,
- String?
+ String,
+ String,
+ String,
+ String,
+ [String]?.JSONRepresentation
) -> Void).self
)
func didUpdate(
recordName: String,
- lastKnownServerRecord: CKRecord?,
- newParentLastKnownServerRecord: CKRecord?,
- parentRecordPrimaryKey: String? = nil,
- parentRecordType: String? = nil
- ) throws {
- let zoneID = lastKnownServerRecord?.recordID.zoneID ?? defaultZone.zoneID
- let newZoneID = newParentLastKnownServerRecord?.recordID.zoneID
- if let newZoneID, zoneID != newZoneID {
- struct ZoneChangingError: Error, LocalizedError {
- let recordName: String
- let zoneID: CKRecordZone.ID
- let newZoneID: CKRecordZone.ID
- var errorDescription: String? {
- """
- The record '\(recordName)' was moved from zone \
- '\(zoneID.zoneName)/\(zoneID.ownerName)' to \
- '\(newZoneID.zoneName)/\(newZoneID.ownerName)'. This is currently not supported in \
- SQLiteData. To work around, delete the record and then create a new record with its \
- new parent association.
- """
- }
+ zoneName: String,
+ ownerName: String,
+ oldZoneName: String,
+ oldOwnerName: String,
+ descendantRecordNames: [String]?
+ ) {
+ var oldChanges: [CKSyncEngine.PendingRecordZoneChange] = []
+ var newChanges: [CKSyncEngine.PendingRecordZoneChange] = []
+
+ let oldZoneID = CKRecordZone.ID(zoneName: oldZoneName, ownerName: oldOwnerName)
+ let zoneID = CKRecordZone.ID(zoneName: zoneName, ownerName: ownerName)
+
+ if oldZoneID != zoneID {
+ oldChanges.append(.deleteRecord(CKRecord.ID(recordName: recordName, zoneID: oldZoneID)))
+ for descendantRecordName in descendantRecordNames ?? [] {
+ oldChanges.append(
+ .deleteRecord(CKRecord.ID(recordName: descendantRecordName, zoneID: oldZoneID))
+ )
+ }
+ newChanges.append(.saveRecord(CKRecord.ID(recordName: recordName, zoneID: zoneID)))
+ for descendantRecordName in descendantRecordNames ?? [] {
+ newChanges.append(
+ .saveRecord(CKRecord.ID(recordName: descendantRecordName, zoneID: zoneID))
+ )
}
- throw ZoneChangingError(recordName: recordName, zoneID: zoneID, newZoneID: newZoneID)
+ } else {
+ newChanges.append(
+ .saveRecord(CKRecord.ID(recordName: recordName, zoneID: zoneID))
+ )
}
- let change = CKSyncEngine.PendingRecordZoneChange.saveRecord(
- CKRecord.ID(
- recordName: recordName,
- zoneID: zoneID
- )
- )
guard isRunning else {
- Task {
+ // TODO: Perform this work in a trigger instead of a task.
+ Task { [changes = oldChanges + newChanges] in
await withErrorReporting(.sqliteDataCloudKitFailure) {
try await userDatabase.write { db in
try PendingRecordZoneChange
- .insert { PendingRecordZoneChange(change) }
+ .insert {
+ for change in changes {
+ PendingRecordZoneChange(change)
+ }
+ }
.execute(db)
}
}
}
return
}
-
+ let oldSyncEngine = self.syncEngines.withValue {
+ oldZoneID.ownerName == CKCurrentUserDefaultName ? $0.private : $0.shared
+ }
let syncEngine = self.syncEngines.withValue {
zoneID.ownerName == CKCurrentUserDefaultName ? $0.private : $0.shared
}
- syncEngine?.state.add(pendingRecordZoneChanges: [change])
+ oldSyncEngine?.state.add(pendingRecordZoneChanges: oldChanges)
+ syncEngine?.state.add(pendingRecordZoneChanges: newChanges)
}
@DatabaseFunction(
@@ -910,7 +916,7 @@
catching: {
try await metadatabase.read { db in
try SyncMetadata
- .where { $0.recordName.eq(recordID.recordName) }
+ .find(recordID)
.select { ($0, $0._lastKnownServerRecordAllFields) }
.fetchOne(db)
}
@@ -959,7 +965,7 @@
record.parent = CKRecord.Reference(
recordID: CKRecord.ID(
recordName: parentRecordName,
- zoneID: record.recordID.zoneID
+ zoneID: recordID.zoneID
),
action: .none
)
@@ -998,22 +1004,26 @@
return nil
}
}
- let deletedRecordNames = deletedRecordIDs.map(\.recordName)
let (sharesToDelete, recordsWithRoot):
([CKShare?], [(lastKnownServerRecord: CKRecord?, rootLastKnownServerRecord: CKRecord?)]) =
await withErrorReporting(.sqliteDataCloudKitFailure) {
- try await metadatabase.read { db in
+ guard !deletedRecordIDs.isEmpty
+ else { return ([], []) }
+
+ return try await metadatabase.read { db in
let sharesToDelete =
try SyncMetadata
- .where { $0.isShared && $0.recordName.in(deletedRecordNames) }
+ .findAll(deletedRecordIDs)
+ .where(\.isShared)
.select(\.share)
.fetchAll(db)
let recordsWithRoot =
try With {
SyncMetadata
- .where { $0.parentRecordName.is(nil) && $0.recordName.in(deletedRecordNames) }
+ .findAll(deletedRecordIDs)
+ .where { $0.parentRecordName.is(nil) }
.select {
RecordWithRoot.Columns(
parentRecordName: $0.parentRecordName,
@@ -1039,7 +1049,6 @@
)
} query: {
RecordWithRoot
- .where { $0.recordName.in(deletedRecordNames) }
.select { ($0.lastKnownServerRecord, $0.rootLastKnownServerRecord) }
}
.fetchAll(db)
@@ -1067,9 +1076,11 @@
}
await withErrorReporting(.sqliteDataCloudKitFailure) {
+ guard !deletedRecordIDs.isEmpty
+ else { return }
try await userDatabase.write { db in
try SyncMetadata
- .where { $0.recordName.in(deletedRecordNames) }
+ .findAll(deletedRecordIDs)
.delete()
.execute(db)
}
@@ -1211,15 +1222,15 @@
)
.mapValues { $0.map(\.recordID) }
for (recordType, recordIDs) in deletedRecordIDsByRecordType {
- let recordPrimaryKeys = recordIDs.compactMap(\.recordPrimaryKey)
if let table = tablesByName[recordType] {
func open(_: T.Type) async {
await withErrorReporting(.sqliteDataCloudKitFailure) {
try await userDatabase.write { db in
try T
.where {
- $0.primaryKey.in(
- recordPrimaryKeys.map { #sql("\(bind: $0)") }
+ #sql("\($0.primaryKey)").in(
+ SyncMetadata.findAll(recordIDs)
+ .select(\.recordPrimaryKey)
)
}
.delete()
@@ -1234,9 +1245,9 @@
}
await open(table)
} else if recordType == CKRecord.SystemType.share {
- for recordID in recordIDs {
+ for shareRecordID in recordIDs {
await withErrorReporting(.sqliteDataCloudKitFailure) {
- try await deleteShare(recordID: recordID)
+ try await deleteShare(shareRecordID: shareRecordID)
}
}
} else {
@@ -1359,7 +1370,7 @@
await withErrorReporting(.sqliteDataCloudKitFailure) {
try await userDatabase.write { db in
try SyncMetadata
- .where { $0.recordName.eq(failedRecord.recordID.recordName) }
+ .find(failedRecord.recordID)
.update { $0.setLastKnownServerRecord(nil) }
.execute(db)
}
@@ -1513,24 +1524,29 @@
else { return }
try await userDatabase.write { db in
try SyncMetadata
- .where { $0.recordName.eq(rootRecordID.recordName) }
+ .find(rootRecordID)
.update { $0.share = share }
.execute(db)
}
}
- func deleteShare(recordID: CKRecord.ID) async throws {
+ func deleteShare(shareRecordID: CKRecord.ID) async throws {
try await userDatabase.write { db in
- let shareAndRecordName =
+ let shareAndRecordNameAndZone =
try SyncMetadata
.where(\.isShared)
- .select { ($0.share, $0.recordName) }
+ .select { ($0.share, $0.recordName, $0.zoneName, $0.ownerName) }
.fetchAll(db)
- .first(where: { share, _ in share?.recordID == recordID }) ?? nil
- guard let (_, recordName) = shareAndRecordName
+ .first(where: { share, _, _, _ in share?.recordID == shareRecordID }) ?? nil
+ guard let (_, recordName, zoneName, ownerName) = shareAndRecordNameAndZone
else { return }
try SyncMetadata
- .where { $0.recordName.eq(recordName) }
+ .find(
+ CKRecord.ID(
+ recordName: recordName,
+ zoneID: CKRecordZone.ID(zoneName: zoneName, ownerName: ownerName)
+ )
+ )
.update { $0.share = nil }
.execute(db)
}
@@ -1553,70 +1569,66 @@
db: Database
) {
withErrorReporting(.sqliteDataCloudKitFailure) {
- guard let table = tablesByName[serverRecord.recordType]
- else {
- guard let recordPrimaryKey = serverRecord.recordID.recordPrimaryKey
- else { return }
- try SyncMetadata.insert {
- SyncMetadata(
- recordPrimaryKey: recordPrimaryKey,
- recordType: serverRecord.recordType,
- zoneName: serverRecord.recordID.zoneID.zoneName,
- ownerName: serverRecord.recordID.zoneID.ownerName,
- parentRecordPrimaryKey: serverRecord.parent?.recordID.recordPrimaryKey,
- parentRecordType: serverRecord.parent?.recordID.tableName,
- lastKnownServerRecord: serverRecord,
- _lastKnownServerRecordAllFields: serverRecord,
- share: nil,
- userModificationTime: serverRecord.userModificationTime
- )
- } onConflict: {
- ($0.recordPrimaryKey, $0.recordType)
- } doUpdate: {
+ guard let recordPrimaryKey = serverRecord.recordID.recordPrimaryKey
+ else { return }
+
+ try SyncMetadata.insert {
+ SyncMetadata(
+ recordPrimaryKey: recordPrimaryKey,
+ recordType: serverRecord.recordType,
+ zoneName: serverRecord.recordID.zoneID.zoneName,
+ ownerName: serverRecord.recordID.zoneID.ownerName,
+ parentRecordPrimaryKey: serverRecord.parent?.recordID.recordPrimaryKey,
+ parentRecordType: serverRecord.parent?.recordID.tableName,
+ lastKnownServerRecord: serverRecord,
+ _lastKnownServerRecordAllFields: serverRecord,
+ share: nil,
+ userModificationTime: serverRecord.userModificationTime
+ )
+ } onConflict: {
+ ($0.recordPrimaryKey, $0.recordType)
+ } doUpdate: {
+ if tablesByName[serverRecord.recordType] == nil {
$0.setLastKnownServerRecord(serverRecord)
+ } else {
+ $0.zoneName = serverRecord.recordID.zoneID.zoneName
+ $0.ownerName = serverRecord.recordID.zoneID.ownerName
}
- .execute(db)
+ }
+ .execute(db)
+
+ guard
+ let metadata = try SyncMetadata.find(serverRecord.recordID).fetchOne(db),
+ let table = tablesByName[serverRecord.recordType]
+ else {
return
}
- let metadata =
- try SyncMetadata
- .where { $0.recordName.eq(serverRecord.recordID.recordName) }
- .fetchOne(db)
- serverRecord.userModificationTime =
- metadata?.userModificationTime ?? serverRecord.userModificationTime
+ serverRecord.userModificationTime = metadata.userModificationTime
func open(_: T.Type) throws {
- let columnNames: [String]
- if !force, let metadata, let allFields = metadata._lastKnownServerRecordAllFields {
- var _columnNames = T.TableColumns.writableColumns.map(\.name)
+ var columnNames: [String] = T.TableColumns.writableColumns.map(\.name)
+ if !force,
+ let allFields = metadata._lastKnownServerRecordAllFields,
let row = try T.find(#sql("\(bind: metadata.recordPrimaryKey)")).fetchOne(db)
- if let row {
- serverRecord.update(
- with: allFields,
- row: T(queryOutput: row),
- columnNames: &_columnNames,
- parentForeignKey: foreignKeysByTableName[T.tableName]?.count == 1
- ? foreignKeysByTableName[T.tableName]?.first
- : nil
- )
- } else {
- reportIssue(
- """
- Local database record could not be found for '\(serverRecord.recordID.recordName)'.
- """
- )
- }
- columnNames = _columnNames
- } else {
- columnNames = T.TableColumns.writableColumns.map(\.name)
+ {
+ serverRecord.update(
+ with: allFields,
+ row: T(queryOutput: row),
+ columnNames: &columnNames,
+ parentForeignKey: foreignKeysByTableName[T.tableName]?.count == 1
+ ? foreignKeysByTableName[T.tableName]?.first
+ : nil
+ )
}
do {
- try #sql(upsert(T.self, record: serverRecord, columnNames: columnNames)).execute(db)
+ try $_currentZoneID.withValue(serverRecord.recordID.zoneID) {
+ try #sql(upsert(T.self, record: serverRecord, columnNames: columnNames)).execute(db)
+ }
try UnsyncedRecordID.find(serverRecord.recordID).delete().execute(db)
try SyncMetadata
- .where { $0.recordName.eq(serverRecord.recordID.recordName) }
+ .find(serverRecord.recordID)
.update { $0.setLastKnownServerRecord(serverRecord) }
.execute(db)
} catch {
@@ -1638,35 +1650,25 @@
}
private func refreshLastKnownServerRecord(_ record: CKRecord) async {
- let metadata = await metadataFor(recordName: record.recordID.recordName)
-
- func updateLastKnownServerRecord() async {
- await withErrorReporting(.sqliteDataCloudKitFailure) {
- try await userDatabase.write { db in
+ await withErrorReporting(.sqliteDataCloudKitFailure) {
+ try await metadatabase.write { db in
+ let metadata = try SyncMetadata.find(record.recordID).fetchOne(db)
+ func updateLastKnownServerRecord() throws {
try SyncMetadata
- .where { $0.recordName.eq(record.recordID.recordName) }
+ .find(record.recordID)
.update { $0.setLastKnownServerRecord(record) }
.execute(db)
}
- }
- }
- if let lastKnownDate = metadata?.lastKnownServerRecord?.modificationDate {
- if let recordDate = record.modificationDate, lastKnownDate < recordDate {
- await updateLastKnownServerRecord()
- }
- } else {
- await updateLastKnownServerRecord()
- }
- }
-
- private func metadataFor(recordName: String) async -> SyncMetadata? {
- await withErrorReporting(.sqliteDataCloudKitFailure) {
- try await metadatabase.read { db in
- try SyncMetadata.where { $0.recordName.eq(recordName) }.fetchOne(db)
+ if let lastKnownDate = metadata?.lastKnownServerRecord?.modificationDate {
+ if let recordDate = record.modificationDate, lastKnownDate < recordDate {
+ try updateLastKnownServerRecord()
+ }
+ } else {
+ try updateLastKnownServerRecord()
+ }
}
}
- ?? nil
}
private func updateQuery(
@@ -1747,7 +1749,7 @@
extension CKRecord.ID {
var tableName: String? {
guard
- let i = recordName.utf8.lastIndex(of: .init(ascii: ":")),
+ let i = recordName.utf8.lastIndex(of: UTF8.CodeUnit(ascii: ":")),
let j = recordName.utf8.index(i, offsetBy: 1, limitedBy: recordName.utf8.endIndex)
else { return nil }
let recordTypeBytes = recordName.utf8[j...]
@@ -1757,7 +1759,7 @@
var recordPrimaryKey: String? {
guard
- let i = recordName.utf8.lastIndex(of: .init(ascii: ":"))
+ let i = recordName.utf8.lastIndex(of: UTF8.CodeUnit(ascii: ":"))
else { return nil }
let recordPrimaryKeyBytes = recordName.utf8[.. String? {
+ _currentZoneID?.zoneName
+ }
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ @DatabaseFunction("sqlitedata_icloud_currentOwnerName")
+ func currentOwnerName() -> String? {
+ _currentZoneID?.ownerName
+ }
#endif
diff --git a/Sources/SQLiteData/CloudKit/SyncMetadata.swift b/Sources/SQLiteData/CloudKit/SyncMetadata.swift
index c5e06857..44672565 100644
--- a/Sources/SQLiteData/CloudKit/SyncMetadata.swift
+++ b/Sources/SQLiteData/CloudKit/SyncMetadata.swift
@@ -85,35 +85,6 @@
public var userModificationTime: Int64
}
- @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
- @Table @Selection
- struct AncestorMetadata {
- let recordName: String
- let parentRecordName: String?
- @Column(as: CKRecord?.SystemFieldsRepresentation.self)
- let lastKnownServerRecord: CKRecord?
- }
-
- @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
- @Table @Selection
- struct RecordWithRoot {
- let parentRecordName: String?
- let recordName: String
- @Column(as: CKRecord?.SystemFieldsRepresentation.self)
- let lastKnownServerRecord: CKRecord?
- let rootRecordName: String
- @Column(as: CKRecord?.SystemFieldsRepresentation.self)
- let rootLastKnownServerRecord: CKRecord?
- }
-
- @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
- @Table @Selection
- struct RootShare {
- let parentRecordName: String?
- @Column(as: CKShare?.SystemFieldsRepresentation.self)
- let share: CKShare?
- }
-
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
extension SyncMetadata {
package init(
@@ -147,6 +118,24 @@
self.isShared = share != nil
self.userModificationTime = userModificationTime
}
+
+ package static func find(_ recordID: CKRecord.ID) -> Where {
+ Self.where {
+ $0.recordName.eq(recordID.recordName)
+ && $0.zoneName.eq(recordID.zoneID.zoneName)
+ && $0.ownerName.eq(recordID.zoneID.ownerName)
+ }
+ }
+
+ package static func findAll(_ recordIDs: some Collection) -> Where {
+ let condition: QueryFragment = recordIDs.map {
+ "(\(bind: $0.recordName), \(bind: $0.zoneID.zoneName), \(bind: $0.zoneID.ownerName))"
+ }
+ .joined(separator: ", ")
+ return Self.where {
+ #sql("(\($0.recordName), \($0.zoneName), \($0.ownerName)) IN (\(condition))")
+ }
+ }
}
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
diff --git a/Sources/SQLiteData/Documentation.docc/Articles/CloudKit.md b/Sources/SQLiteData/Documentation.docc/Articles/CloudKit.md
index e9f1ead0..6e2c2350 100644
--- a/Sources/SQLiteData/Documentation.docc/Articles/CloudKit.md
+++ b/Sources/SQLiteData/Documentation.docc/Articles/CloudKit.md
@@ -287,7 +287,7 @@ has been added to the schema, it will populate the table with the cached records
#### Adding columns
> TL;DR: When adding columns to a table that has already been deployed to users' devices, you will
-either need to make the column nullable, or a default value must be provided with an
+either need to make the column nullable, or a default value must be provided with an
`ON CONFLICT REPLACE` clause.
As an example, suppose the 1.0 of your app shipped a table for a reminders list:
diff --git a/Sources/SQLiteData/Documentation.docc/Articles/Observing.md b/Sources/SQLiteData/Documentation.docc/Articles/Observing.md
index f57feb5f..f1ce70e5 100644
--- a/Sources/SQLiteData/Documentation.docc/Articles/Observing.md
+++ b/Sources/SQLiteData/Documentation.docc/Articles/Observing.md
@@ -1,7 +1,7 @@
# Observing changes to model data
-Learn how to observe changes to your database in SwiftUI views, UIKit view controllers, and
-more.
+Learn how to observe changes to your database in SwiftUI views, UIKit view controllers, and
+more.
## Overview
diff --git a/Sources/SQLiteData/Documentation.docc/Articles/PreparingDatabase.md b/Sources/SQLiteData/Documentation.docc/Articles/PreparingDatabase.md
index f1a21b36..eadbdac1 100644
--- a/Sources/SQLiteData/Documentation.docc/Articles/PreparingDatabase.md
+++ b/Sources/SQLiteData/Documentation.docc/Articles/PreparingDatabase.md
@@ -1,6 +1,6 @@
# Preparing a SQLite database
-Learn how to create, configure and migrate the SQLite database that holds your applicationβs
+Learn how to create, configure and migrate the SQLite database that holds your applicationβs
data.
## Overview
@@ -46,10 +46,10 @@ optional step:
}
```
-One configuration you may want to enable is query tracing in order to log queries that are executed
-in your application. This can be handy for tracking down long-running queries, or when more queries
-execute than you expect. We also recommend only doing this in debug builds to avoid leaking
-sensitive information when the app is running on a user's device, and we further recommend using
+One configuration you may want to enable is query tracing in order to log queries that are executed
+in your application. This can be handy for tracking down long-running queries, or when more queries
+execute than you expect. We also recommend only doing this in debug builds to avoid leaking
+sensitive information when the app is running on a user's device, and we further recommend using
OSLog when running your app in the simulator/device and using `Swift.print` in previews:
```diff
@@ -85,7 +85,7 @@ OSLog when running your app in the simulator/device and using `Swift.print` in p
[swift-dependencies-gh]: https://github.com/pointfreeco/swift-dependencies
-For more information on configuring the database connection, see [GRDB's documentation][config-docs]
+For more information on configuring the database connection, see [GRDB's documentation][config-docs]
on the matter.
[config-docs]: https://swiftpackageindex.com/groue/grdb.swift/master/documentation/grdb/configuration
diff --git a/Sources/SQLiteData/Documentation.docc/SQLiteData.md b/Sources/SQLiteData/Documentation.docc/SQLiteData.md
index 2112fd3d..c9a3bc32 100644
--- a/Sources/SQLiteData/Documentation.docc/SQLiteData.md
+++ b/Sources/SQLiteData/Documentation.docc/SQLiteData.md
@@ -1,6 +1,6 @@
# ``SQLiteData``
-A fast, lightweight replacement for SwiftData, powered by SQL and supporting CloudKit
+A fast, lightweight replacement for SwiftData, powered by SQL and supporting CloudKit
synchronization.
## Overview
diff --git a/Tests/SQLiteDataTests/AssertQueryTests.swift b/Tests/SQLiteDataTests/AssertQueryTests.swift
index 4878a923..4dfb959a 100644
--- a/Tests/SQLiteDataTests/AssertQueryTests.swift
+++ b/Tests/SQLiteDataTests/AssertQueryTests.swift
@@ -7,7 +7,7 @@ import Testing
@Suite(
.dependency(\.defaultDatabase, try .database()),
- .snapshots(record: .failed),
+ .snapshots(record: .missing),
)
struct AssertQueryTests {
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
diff --git a/Tests/SQLiteDataTests/CloudKitTests/AccountLifecycleTests.swift b/Tests/SQLiteDataTests/CloudKitTests/AccountLifecycleTests.swift
index f8670788..e5865a70 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/AccountLifecycleTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/AccountLifecycleTests.swift
@@ -357,7 +357,8 @@
_ = try syncEngine.modifyRecords(scope: .shared, saving: [share, remindersListRecord])
let freshShare = try syncEngine.shared.database.record(for: share.recordID) as! CKShare
- let freshRemindersListRecord = try syncEngine.shared.database.record(for: remindersListRecord.recordID)
+ let freshRemindersListRecord = try syncEngine.shared.database.record(
+ for: remindersListRecord.recordID)
try await syncEngine
.acceptShare(
diff --git a/Tests/SQLiteDataTests/CloudKitTests/AppLifecycleTests.swift b/Tests/SQLiteDataTests/CloudKitTests/AppLifecycleTests.swift
index 59033c08..e6af0fd2 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/AppLifecycleTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/AppLifecycleTests.swift
@@ -23,7 +23,8 @@
RemindersList(id: 1, title: "Personal")
}
}
- defaultNotificationCenter.post(name: UIApplication.willResignActiveNotification, object: nil)
+ defaultNotificationCenter.post(
+ name: UIApplication.willResignActiveNotification, object: nil)
try await Task.sleep(for: .seconds(1))
assertInlineSnapshot(of: container, as: .customDump) {
"""
@@ -90,7 +91,8 @@
}
}
- defaultNotificationCenter.post(name: UIApplication.willResignActiveNotification, object: nil)
+ defaultNotificationCenter.post(
+ name: UIApplication.willResignActiveNotification, object: nil)
try await Task.sleep(for: .seconds(1))
assertInlineSnapshot(of: container, as: .customDump) {
"""
diff --git a/Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift b/Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift
index 57eb9b3c..460c27da 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift
@@ -447,11 +447,13 @@
) {
"""
[
- [0]: "sqlitedata_icloud_currenttime",
- [1]: "sqlitedata_icloud_diddelete",
- [2]: "sqlitedata_icloud_didupdate",
- [3]: "sqlitedata_icloud_haspermission",
- [4]: "sqlitedata_icloud_syncengineissynchronizingchanges"
+ [0]: "sqlitedata_icloud_currentownername",
+ [1]: "sqlitedata_icloud_currenttime",
+ [2]: "sqlitedata_icloud_currentzonename",
+ [3]: "sqlitedata_icloud_diddelete",
+ [4]: "sqlitedata_icloud_didupdate",
+ [5]: "sqlitedata_icloud_haspermission",
+ [6]: "sqlitedata_icloud_syncengineissynchronizingchanges"
]
"""
}
diff --git a/Tests/SQLiteDataTests/CloudKitTests/MergeConflictTests.swift b/Tests/SQLiteDataTests/CloudKitTests/MergeConflictTests.swift
index 645540a0..e3a5964a 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/MergeConflictTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/MergeConflictTests.swift
@@ -629,27 +629,26 @@
let reminderRecord = try syncEngine.private.database.record(
for: Reminder.recordID(for: 1)
)
- reminderRecord.setValue(Date(
- timeIntervalSince1970: Double(now + 30)),
+ reminderRecord.setValue(
+ Date(timeIntervalSince1970: Double(now + 30)),
forKey: "dueDate",
- at: now + 1
+ at: now
)
let modificationsFinished = try syncEngine.modifyRecords(
scope: .private,
saving: [reminderRecord]
)
- try withDependencies {
- $0.currentTime.now += 2
+ try await withDependencies {
+ $0.currentTime.now += 1
} operation: {
- try userDatabase.userWrite { db in
+ try await userDatabase.userWrite { db in
try Reminder.find(1).update { $0.priority = 3 }.execute(db)
}
+ await modificationsFinished.notify()
+ try await syncEngine.processPendingRecordZoneChanges(scope: .private)
}
- await modificationsFinished.notify()
- try await syncEngine.processPendingRecordZoneChanges(scope: .private)
-
assertInlineSnapshot(of: container, as: .customDump) {
"""
MockCloudContainer(
@@ -662,18 +661,18 @@
parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)),
share: nil,
dueDate: Date(1970-01-01T00:00:30.000Z),
- dueDateποΈ: 1,
+ dueDateποΈ: 0,
id: 1,
idποΈ: 0,
isCompleted: 0,
isCompletedποΈ: 0,
priority: 3,
- priorityποΈ: 2,
+ priorityποΈ: 1,
remindersListID: 1,
remindersListIDποΈ: 0,
title: "",
titleποΈ: 0,
- ποΈ: 2
+ ποΈ: 1
),
[1]: CKRecord(
recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__),
diff --git a/Tests/SQLiteDataTests/CloudKitTests/MockCloudDatabaseTests.swift b/Tests/SQLiteDataTests/CloudKitTests/MockCloudDatabaseTests.swift
index 3df8dfc9..963599f7 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/MockCloudDatabaseTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/MockCloudDatabaseTests.swift
@@ -392,7 +392,8 @@
try withKnownIssue {
_ = try syncEngine.modifyRecords(scope: .private, saving: [share])
} matching: { issue in
- issue.description.hasSuffix("""
+ issue.description.hasSuffix(
+ """
An added share is being saved without its rootRecord being saved in the \
same operation.
""")
diff --git a/Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift b/Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift
index af13f787..839f2df7 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift
@@ -48,7 +48,7 @@
.execute(db)
}
- try await syncEngine.processPendingRecordZoneChanges(scope: .private)
+ try await syncEngine.processPendingRecordZoneChanges(scope: .shared)
assertInlineSnapshot(of: container, as: .customDump) {
"""
MockCloudContainer(
diff --git a/Tests/SQLiteDataTests/CloudKitTests/RecordTypeTests.swift b/Tests/SQLiteDataTests/CloudKitTests/RecordTypeTests.swift
index fd1a0a10..20bf20a3 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/RecordTypeTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/RecordTypeTests.swift
@@ -394,7 +394,7 @@
try #expect(RecordType.all.fetchCount(db) > 0)
try #expect(StateSerialization.all.fetchCount(db) == 0)
}
-
+
try syncEngine.tearDownSyncEngine()
try await syncEngine.metadatabase.read { db in
try #expect(SyncMetadata.all.fetchCount(db) == 0)
diff --git a/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift b/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift
index 67e7e714..9b4c2f54 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift
@@ -835,18 +835,78 @@
try await syncEngine.processPendingRecordZoneChanges(scope: .shared)
- assertQuery(
- SyncMetadata.select { ($0.recordName, $0.parentRecordName) },
- database: syncEngine.metadatabase
- ) {
+ assertQuery(SyncMetadata.all, database: syncEngine.metadatabase) {
"""
- ββββββββββββββββββββββ¬βββββββββββββββββββββ
- β "1:remindersLists" β nil β
- β "1:reminders" β "1:remindersLists" β
- ββββββββββββββββββββββ΄βββββββββββββββββββββ
+ βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "remindersLists", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:remindersLists", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner), β
+ β recordType: "remindersLists", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-1:remindersLists/external.zone/external.owner)) β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner), β
+ β recordType: "remindersLists", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-1:remindersLists/external.zone/external.owner)), β
+ β id: 1, β
+ β title: "Personal" β
+ β ), β
+ β share: CKRecord( β
+ β recordID: CKRecord.ID(share-1:remindersLists/external.zone/external.owner), β
+ β recordType: "cloudkit.share", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: true, β
+ β userModificationTime: 0 β
+ β ) β
+ βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "reminders", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:reminders", β
+ β parentRecordPrimaryKey: "1", β
+ β parentRecordType: "remindersLists", β
+ β parentRecordName: "1:remindersLists", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:reminders/external.zone/external.owner), β
+ β recordType: "reminders", β
+ β parent: CKReference(recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:reminders/external.zone/external.owner), β
+ β recordType: "reminders", β
+ β parent: CKReference(recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β isCompleted: 0, β
+ β remindersListID: 1, β
+ β title: "Get milk" β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
"""
}
-
assertInlineSnapshot(of: container, as: .customDump) {
"""
MockCloudContainer(
@@ -964,6 +1024,7 @@
try await userDatabase.userWrite { db in
try db.seed {
Reminder(id: 1, title: "Get milk", remindersListID: 1)
+ Reminder(id: 2, title: "Take a walk", remindersListID: 1)
}
}
@@ -975,13 +1036,9 @@
try await syncEngine.processPendingRecordZoneChanges(scope: .shared)
- assertQuery(
- SyncMetadata.select { ($0.recordName, $0.share) },
- database: syncEngine.metadatabase
- ) {
- """
- """
- }
+ assertQuery(Reminder.all, database: userDatabase.database)
+ assertQuery(RemindersList.all, database: userDatabase.database)
+ assertQuery(SyncMetadata.all, database: syncEngine.metadatabase)
assertInlineSnapshot(of: container, as: .customDump) {
"""
@@ -1004,6 +1061,16 @@
title: "Get milk"
),
[1]: CKRecord(
+ recordID: CKRecord.ID(2:reminders/external.zone/external.owner),
+ recordType: "reminders",
+ parent: CKReference(recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner)),
+ share: nil,
+ id: 2,
+ isCompleted: 0,
+ remindersListID: 1,
+ title: "Take a walk"
+ ),
+ [2]: CKRecord(
recordID: CKRecord.ID(1:remindersLists/external.zone/external.owner),
recordType: "remindersLists",
parent: nil,
@@ -1018,12 +1085,69 @@
}
}
+ // NB: Come back to this when we have time to investigate.
+ // /// Deleting a root shared record that is not owned by current user should only delete
+ // /// the CKShare, not delete the actual CloudKit records, but delete all the local records.
+ // @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ // @Test func deleteRootSharedRecord_OnDeleteSetNull() async throws {
+ // let externalZone = CKRecordZone(
+ // zoneID: CKRecordZone.ID(
+ // zoneName: "external.zone",
+ // ownerName: "external.owner"
+ // )
+ // )
+ // try await syncEngine.modifyRecordZones(scope: .shared, saving: [externalZone]).notify()
+ //
+ // let parentRecord = CKRecord(
+ // recordType: Parent.tableName,
+ // recordID: Parent.recordID(for: 1, zoneID: externalZone.zoneID)
+ // )
+ // parentRecord.setValue(1, forKey: "id", at: now)
+ // let share = CKShare(
+ // rootRecord: parentRecord,
+ // shareID: CKRecord.ID(
+ // recordName: "share-\(parentRecord.recordID.recordName)",
+ // zoneID: parentRecord.recordID.zoneID
+ // )
+ // )
+ //
+ // try await syncEngine
+ // .acceptShare(
+ // metadata: ShareMetadata(
+ // containerIdentifier: container.containerIdentifier!,
+ // hierarchicalRootRecordID: parentRecord.recordID,
+ // rootRecord: parentRecord,
+ // share: share
+ // )
+ // )
+ //
+ // try await userDatabase.userWrite { db in
+ // try db.seed {
+ // ChildWithOnDeleteSetNull(id: 1, parentID: 1)
+ // }
+ // }
+ //
+ // try await syncEngine.processPendingRecordZoneChanges(scope: .shared)
+ //
+ // try await userDatabase.userWrite { db in
+ // try Parent.find(1).delete().execute(db)
+ // }
+ //
+ // try await syncEngine.processPendingRecordZoneChanges(scope: .shared)
+ //
+ // assertQuery(Parent.all, database: userDatabase.database)
+ // assertQuery(ChildWithOnDeleteSetNull.all, database: userDatabase.database)
+ // assertQuery(SyncMetadata.all, database: syncEngine.metadatabase)
+ // assertInlineSnapshot(of: container, as: .customDump)
+ // }
+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
@Test func movesChildRecordFromPrivateParentToSharedParent() async throws {
try await userDatabase.userWrite { db in
try db.seed {
ModelA.Draft(id: 1, count: 42)
ModelB.Draft(id: 1, isOn: true, modelAID: 1)
+ ModelC.Draft(id: 1, title: "Blob", modelBID: 1)
}
}
try await syncEngine.processPendingRecordZoneChanges(scope: .private)
@@ -1063,16 +1187,16 @@
)
)
- let error = await #expect(throws: DatabaseError.self) {
+ try await withDependencies {
+ $0.currentTime.now += 1
+ } operation: {
try await self.userDatabase.userWrite { db in
try ModelB.find(1).update { $0.modelAID = 2 }.execute(db)
}
+
+ try await syncEngine.processPendingRecordZoneChanges(scope: .private)
+ try await syncEngine.processPendingRecordZoneChanges(scope: .shared)
}
- #expect(error?.message == """
- The record '1:modelBs' was moved from zone 'zone/__defaultOwner__' to \
- 'external.zone/external.owner'. This is currently not supported in SQLiteData. To work \
- around, delete the record and then create a new record with its new parent association.
- """)
assertQuery(ModelB.all, database: userDatabase.database) {
"""
@@ -1080,12 +1204,26 @@
β ModelB( β
β id: 1, β
β isOn: true, β
- β modelAID: 1 β
+ β modelAID: 2 β
β ) β
βββββββββββββββββ
"""
}
- assertQuery(SyncMetadata.all, database: syncEngine.metadatabase) {
+ assertQuery(ModelC.all, database: userDatabase.database) {
+ """
+ ββββββββββββββββββββ
+ β ModelC( β
+ β id: 1, β
+ β title: "Blob", β
+ β modelBID: 1 β
+ β ) β
+ ββββββββββββββββββββ
+ """
+ }
+ assertQuery(
+ SyncMetadata.order { ($0.recordType, $0.recordName) },
+ database: syncEngine.metadatabase
+ ) {
"""
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SyncMetadata( β
@@ -1119,37 +1257,6 @@
β ) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β SyncMetadata( β
- β recordPrimaryKey: "1", β
- β recordType: "modelBs", β
- β zoneName: "zone", β
- β ownerName: "__defaultOwner__", β
- β recordName: "1:modelBs", β
- β parentRecordPrimaryKey: "1", β
- β parentRecordType: "modelAs", β
- β parentRecordName: "1:modelAs", β
- β lastKnownServerRecord: CKRecord( β
- β recordID: CKRecord.ID(1:modelBs/zone/__defaultOwner__), β
- β recordType: "modelBs", β
- β parent: CKReference(recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__)), β
- β share: nil β
- β ), β
- β _lastKnownServerRecordAllFields: CKRecord( β
- β recordID: CKRecord.ID(1:modelBs/zone/__defaultOwner__), β
- β recordType: "modelBs", β
- β parent: CKReference(recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__)), β
- β share: nil, β
- β id: 1, β
- β isOn: 1, β
- β modelAID: 1 β
- β ), β
- β share: nil, β
- β _isDeleted: false, β
- β hasLastKnownServerRecord: true, β
- β isShared: false, β
- β userModificationTime: 0 β
- β ) β
- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
- β SyncMetadata( β
β recordPrimaryKey: "2", β
β recordType: "modelAs", β
β zoneName: "external.zone", β
@@ -1183,6 +1290,68 @@
β isShared: true, β
β userModificationTime: 0 β
β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelBs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:modelBs", β
+ β parentRecordPrimaryKey: "2", β
+ β parentRecordType: "modelAs", β
+ β parentRecordName: "2:modelAs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β isOn: 1, β
+ β modelAID: 2 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 1 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelCs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:modelCs", β
+ β parentRecordPrimaryKey: "1", β
+ β parentRecordType: "modelBs", β
+ β parentRecordName: "1:modelBs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), β
+ β recordType: "modelCs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), β
+ β recordType: "modelCs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β modelBID: 1, β
+ β title: "Blob" β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
"""
}
@@ -1199,15 +1368,6 @@
share: nil,
count: 42,
id: 1
- ),
- [1]: CKRecord(
- recordID: CKRecord.ID(1:modelBs/zone/__defaultOwner__),
- recordType: "modelBs",
- parent: CKReference(recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__)),
- share: nil,
- id: 1,
- isOn: 1,
- modelAID: 1
)
]
),
@@ -1227,6 +1387,1121 @@
share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)),
count: 1729,
id: 2
+ ),
+ [2]: CKRecord(
+ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner),
+ recordType: "modelBs",
+ parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)),
+ share: nil,
+ id: 1,
+ isOn: 1,
+ modelAID: 2
+ ),
+ [3]: CKRecord(
+ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner),
+ recordType: "modelCs",
+ parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)),
+ share: nil,
+ id: 1,
+ modelBID: 1,
+ title: "Blob"
+ )
+ ]
+ )
+ )
+ """
+ }
+ }
+
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ @Test func movesChildRecordFromPrivateParentToSharedParent_ReceiveDeleteBeforeSave()
+ async throws
+ {
+ try await userDatabase.userWrite { db in
+ try db.seed {
+ ModelA.Draft(id: 1, count: 42)
+ ModelB.Draft(id: 1, isOn: true, modelAID: 1)
+ ModelC.Draft(id: 1, title: "Blob", modelBID: 1)
+ }
+ }
+ try await syncEngine.processPendingRecordZoneChanges(scope: .private)
+
+ let externalZone = CKRecordZone(
+ zoneID: CKRecordZone.ID(
+ zoneName: "external.zone",
+ ownerName: "external.owner"
+ )
+ )
+ try await syncEngine.modifyRecordZones(scope: .shared, saving: [externalZone]).notify()
+
+ let modelARecord = CKRecord(
+ recordType: ModelA.tableName,
+ recordID: ModelA.recordID(for: 2, zoneID: externalZone.zoneID)
+ )
+ modelARecord.setValue(2, forKey: "id", at: now)
+ modelARecord.setValue(1729, forKey: "count", at: now)
+ let share = CKShare(
+ rootRecord: modelARecord,
+ shareID: CKRecord.ID(
+ recordName: "share-\(modelARecord.recordID.recordName)",
+ zoneID: modelARecord.recordID.zoneID
+ )
+ )
+ _ = try syncEngine.modifyRecords(scope: .shared, saving: [share, modelARecord])
+ let freshShare = try syncEngine.shared.database.record(for: share.recordID) as! CKShare
+ let freshModelARecord = try syncEngine.shared.database.record(for: modelARecord.recordID)
+
+ try await syncEngine
+ .acceptShare(
+ metadata: ShareMetadata(
+ containerIdentifier: container.containerIdentifier!,
+ hierarchicalRootRecordID: freshModelARecord.recordID,
+ rootRecord: freshModelARecord,
+ share: freshShare
+ )
+ )
+
+ let movedModelBRecord = CKRecord(
+ recordType: ModelB.tableName,
+ recordID: ModelB.recordID(for: 1, zoneID: externalZone.zoneID)
+ )
+ movedModelBRecord.setValue(1, forKey: "id", at: now)
+ movedModelBRecord.setValue(true, forKey: "isOn", at: now)
+ movedModelBRecord.setValue(2, forKey: "modelAID", at: now)
+ movedModelBRecord.parent = CKRecord.Reference(
+ recordID: ModelA.recordID(for: 2, zoneID: externalZone.zoneID),
+ action: .none
+ )
+ let movedModelCRecord = CKRecord(
+ recordType: ModelC.tableName,
+ recordID: ModelC.recordID(for: 1, zoneID: externalZone.zoneID)
+ )
+ movedModelCRecord.setValue(1, forKey: "id", at: now)
+ movedModelCRecord.setValue("Blob", forKey: "title", at: now)
+ movedModelCRecord.setValue(1, forKey: "modelBID", at: now)
+ movedModelCRecord.parent = CKRecord.Reference(
+ recordID: ModelB.recordID(for: 1, zoneID: externalZone.zoneID),
+ action: .none
+ )
+
+ try await syncEngine.modifyRecords(
+ scope: .private,
+ deleting: [ModelB.recordID(for: 1), ModelC.recordID(for: 1)]
+ ).notify()
+ try await syncEngine.modifyRecords(
+ scope: .shared,
+ saving: [movedModelBRecord, movedModelCRecord]
+ ).notify()
+
+ assertQuery(ModelB.all, database: userDatabase.database) {
+ """
+ βββββββββββββββββ
+ β ModelB( β
+ β id: 1, β
+ β isOn: true, β
+ β modelAID: 2 β
+ β ) β
+ βββββββββββββββββ
+ """
+ }
+ assertQuery(ModelC.all, database: userDatabase.database) {
+ """
+ ββββββββββββββββββββ
+ β ModelC( β
+ β id: 1, β
+ β title: "Blob", β
+ β modelBID: 1 β
+ β ) β
+ ββββββββββββββββββββ
+ """
+ }
+ assertQuery(
+ SyncMetadata.order { ($0.recordType, $0.recordName) },
+ database: syncEngine.metadatabase
+ ) {
+ """
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelAs", β
+ β zoneName: "zone", β
+ β ownerName: "__defaultOwner__", β
+ β recordName: "1:modelAs", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: nil, β
+ β count: 42, β
+ β id: 1 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "2", β
+ β recordType: "modelAs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "2:modelAs", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)) β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)), β
+ β count: 1729, β
+ β id: 2 β
+ β ), β
+ β share: CKRecord( β
+ β recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner), β
+ β recordType: "cloudkit.share", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: true, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelBs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:modelBs", β
+ β parentRecordPrimaryKey: "2", β
+ β parentRecordType: "modelAs", β
+ β parentRecordName: "2:modelAs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β isOn: 1, β
+ β modelAID: 2 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelCs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:modelCs", β
+ β parentRecordPrimaryKey: "1", β
+ β parentRecordType: "modelBs", β
+ β parentRecordName: "1:modelBs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), β
+ β recordType: "modelCs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), β
+ β recordType: "modelCs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β modelBID: 1, β
+ β title: "Blob" β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ """
+ }
+ assertInlineSnapshot(of: container, as: .customDump) {
+ """
+ MockCloudContainer(
+ privateCloudDatabase: MockCloudDatabase(
+ databaseScope: .private,
+ storage: [
+ [0]: CKRecord(
+ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__),
+ recordType: "modelAs",
+ parent: nil,
+ share: nil,
+ count: 42,
+ id: 1
+ )
+ ]
+ ),
+ sharedCloudDatabase: MockCloudDatabase(
+ databaseScope: .shared,
+ storage: [
+ [0]: CKRecord(
+ recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner),
+ recordType: "cloudkit.share",
+ parent: nil,
+ share: nil
+ ),
+ [1]: CKRecord(
+ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner),
+ recordType: "modelAs",
+ parent: nil,
+ share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)),
+ count: 1729,
+ id: 2
+ ),
+ [2]: CKRecord(
+ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner),
+ recordType: "modelBs",
+ parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)),
+ share: nil,
+ id: 1,
+ isOn: 1,
+ modelAID: 2
+ ),
+ [3]: CKRecord(
+ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner),
+ recordType: "modelCs",
+ parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)),
+ share: nil,
+ id: 1,
+ modelBID: 1,
+ title: "Blob"
+ )
+ ]
+ )
+ )
+ """
+ }
+ }
+
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ @Test func movesChildRecordFromPrivateParentToSharedParent_ReceiveSaveBeforeDelete()
+ async throws
+ {
+ try await userDatabase.userWrite { db in
+ try db.seed {
+ ModelA.Draft(id: 1, count: 42)
+ ModelB.Draft(id: 1, isOn: true, modelAID: 1)
+ ModelC.Draft(id: 1, title: "Blob", modelBID: 1)
+ }
+ }
+ try await syncEngine.processPendingRecordZoneChanges(scope: .private)
+
+ let externalZone = CKRecordZone(
+ zoneID: CKRecordZone.ID(
+ zoneName: "external.zone",
+ ownerName: "external.owner"
+ )
+ )
+ try await syncEngine.modifyRecordZones(scope: .shared, saving: [externalZone]).notify()
+
+ let modelARecord = CKRecord(
+ recordType: ModelA.tableName,
+ recordID: ModelA.recordID(for: 2, zoneID: externalZone.zoneID)
+ )
+ modelARecord.setValue(2, forKey: "id", at: now)
+ modelARecord.setValue(1729, forKey: "count", at: now)
+ let share = CKShare(
+ rootRecord: modelARecord,
+ shareID: CKRecord.ID(
+ recordName: "share-\(modelARecord.recordID.recordName)",
+ zoneID: modelARecord.recordID.zoneID
+ )
+ )
+ _ = try syncEngine.modifyRecords(scope: .shared, saving: [share, modelARecord])
+ let freshShare = try syncEngine.shared.database.record(for: share.recordID) as! CKShare
+ let freshModelARecord = try syncEngine.shared.database.record(for: modelARecord.recordID)
+
+ try await syncEngine
+ .acceptShare(
+ metadata: ShareMetadata(
+ containerIdentifier: container.containerIdentifier!,
+ hierarchicalRootRecordID: freshModelARecord.recordID,
+ rootRecord: freshModelARecord,
+ share: freshShare
+ )
+ )
+
+ let movedModelBRecord = CKRecord(
+ recordType: ModelB.tableName,
+ recordID: ModelB.recordID(for: 1, zoneID: externalZone.zoneID)
+ )
+ movedModelBRecord.setValue(1, forKey: "id", at: now)
+ movedModelBRecord.setValue(true, forKey: "isOn", at: now)
+ movedModelBRecord.setValue(2, forKey: "modelAID", at: now)
+ movedModelBRecord.parent = CKRecord.Reference(
+ recordID: ModelA.recordID(for: 2, zoneID: externalZone.zoneID),
+ action: .none
+ )
+ let movedModelCRecord = CKRecord(
+ recordType: ModelC.tableName,
+ recordID: ModelC.recordID(for: 1, zoneID: externalZone.zoneID)
+ )
+ movedModelCRecord.setValue(1, forKey: "id", at: now)
+ movedModelCRecord.setValue("Blob", forKey: "title", at: now)
+ movedModelCRecord.setValue(1, forKey: "modelBID", at: now)
+ movedModelCRecord.parent = CKRecord.Reference(
+ recordID: ModelB.recordID(for: 1, zoneID: externalZone.zoneID),
+ action: .none
+ )
+
+ try await syncEngine.modifyRecords(
+ scope: .shared,
+ saving: [movedModelBRecord, movedModelCRecord]
+ ).notify()
+ try await syncEngine.modifyRecords(
+ scope: .private,
+ deleting: [ModelB.recordID(for: 1), ModelC.recordID(for: 1)]
+ ).notify()
+
+ assertQuery(ModelB.all, database: userDatabase.database) {
+ """
+ βββββββββββββββββ
+ β ModelB( β
+ β id: 1, β
+ β isOn: true, β
+ β modelAID: 2 β
+ β ) β
+ βββββββββββββββββ
+ """
+ }
+ assertQuery(ModelC.all, database: userDatabase.database) {
+ """
+ ββββββββββββββββββββ
+ β ModelC( β
+ β id: 1, β
+ β title: "Blob", β
+ β modelBID: 1 β
+ β ) β
+ ββββββββββββββββββββ
+ """
+ }
+ assertQuery(
+ SyncMetadata.order { ($0.recordType, $0.recordName) },
+ database: syncEngine.metadatabase
+ ) {
+ """
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelAs", β
+ β zoneName: "zone", β
+ β ownerName: "__defaultOwner__", β
+ β recordName: "1:modelAs", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: nil, β
+ β count: 42, β
+ β id: 1 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "2", β
+ β recordType: "modelAs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "2:modelAs", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)) β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)), β
+ β count: 1729, β
+ β id: 2 β
+ β ), β
+ β share: CKRecord( β
+ β recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner), β
+ β recordType: "cloudkit.share", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: true, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelBs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:modelBs", β
+ β parentRecordPrimaryKey: "2", β
+ β parentRecordType: "modelAs", β
+ β parentRecordName: "2:modelAs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β isOn: 1, β
+ β modelAID: 2 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelCs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:modelCs", β
+ β parentRecordPrimaryKey: "1", β
+ β parentRecordType: "modelBs", β
+ β parentRecordName: "1:modelBs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), β
+ β recordType: "modelCs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), β
+ β recordType: "modelCs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β modelBID: 1, β
+ β title: "Blob" β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ """
+ }
+ assertInlineSnapshot(of: container, as: .customDump) {
+ """
+ MockCloudContainer(
+ privateCloudDatabase: MockCloudDatabase(
+ databaseScope: .private,
+ storage: [
+ [0]: CKRecord(
+ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__),
+ recordType: "modelAs",
+ parent: nil,
+ share: nil,
+ count: 42,
+ id: 1
+ )
+ ]
+ ),
+ sharedCloudDatabase: MockCloudDatabase(
+ databaseScope: .shared,
+ storage: [
+ [0]: CKRecord(
+ recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner),
+ recordType: "cloudkit.share",
+ parent: nil,
+ share: nil
+ ),
+ [1]: CKRecord(
+ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner),
+ recordType: "modelAs",
+ parent: nil,
+ share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)),
+ count: 1729,
+ id: 2
+ ),
+ [2]: CKRecord(
+ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner),
+ recordType: "modelBs",
+ parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)),
+ share: nil,
+ id: 1,
+ isOn: 1,
+ modelAID: 2
+ ),
+ [3]: CKRecord(
+ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner),
+ recordType: "modelCs",
+ parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)),
+ share: nil,
+ id: 1,
+ modelBID: 1,
+ title: "Blob"
+ )
+ ]
+ )
+ )
+ """
+ }
+ }
+
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ @Test func movesChildRecordFromSharedParentToPrivateParent() async throws {
+ try await userDatabase.userWrite { db in
+ try db.seed {
+ ModelA.Draft(id: 1, count: 42)
+ }
+ }
+ try await syncEngine.processPendingRecordZoneChanges(scope: .private)
+
+ let externalZone = CKRecordZone(
+ zoneID: CKRecordZone.ID(
+ zoneName: "external.zone",
+ ownerName: "external.owner"
+ )
+ )
+ try await syncEngine.modifyRecordZones(scope: .shared, saving: [externalZone]).notify()
+
+ let modelARecord = CKRecord(
+ recordType: ModelA.tableName,
+ recordID: ModelA.recordID(for: 2, zoneID: externalZone.zoneID)
+ )
+ modelARecord.setValue(2, forKey: "id", at: now)
+ modelARecord.setValue(1729, forKey: "count", at: now)
+ let share = CKShare(
+ rootRecord: modelARecord,
+ shareID: CKRecord.ID(
+ recordName: "share-\(modelARecord.recordID.recordName)",
+ zoneID: modelARecord.recordID.zoneID
+ )
+ )
+ let modelBRecord = CKRecord(
+ recordType: ModelB.tableName,
+ recordID: ModelB.recordID(for: 1, zoneID: externalZone.zoneID)
+ )
+ modelBRecord.setValue(1, forKey: "id", at: now)
+ modelBRecord.setValue(true, forKey: "isOne", at: now)
+ modelBRecord.setValue(1, forKey: "modelAID", at: now)
+ modelBRecord.parent = CKRecord.Reference(record: modelARecord, action: .none)
+
+ _ =
+ try syncEngine
+ .modifyRecords(scope: .shared, saving: [share, modelARecord, modelBRecord])
+ let freshShare = try syncEngine.shared.database.record(for: share.recordID) as! CKShare
+ let freshModelARecord = try syncEngine.shared.database.record(for: modelARecord.recordID)
+
+ try await syncEngine
+ .acceptShare(
+ metadata: ShareMetadata(
+ containerIdentifier: container.containerIdentifier!,
+ hierarchicalRootRecordID: freshModelARecord.recordID,
+ rootRecord: freshModelARecord,
+ share: freshShare
+ )
+ )
+
+ try await withDependencies {
+ $0.currentTime.now += 1
+ } operation: {
+ try await self.userDatabase.userWrite { db in
+ try ModelB.find(1).update { $0.modelAID = 1 }.execute(db)
+ }
+
+ try await syncEngine.processPendingRecordZoneChanges(scope: .private)
+ try await syncEngine.processPendingRecordZoneChanges(scope: .shared)
+ }
+
+ assertQuery(ModelB.all, database: userDatabase.database) {
+ """
+ ββββββββββββββββββ
+ β ModelB( β
+ β id: 1, β
+ β isOn: false, β
+ β modelAID: 1 β
+ β ) β
+ ββββββββββββββββββ
+ """
+ }
+ assertQuery(ModelC.all, database: userDatabase.database)
+ assertQuery(
+ SyncMetadata.order { ($0.recordType, $0.recordName) },
+ database: syncEngine.metadatabase
+ ) {
+ """
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelAs", β
+ β zoneName: "zone", β
+ β ownerName: "__defaultOwner__", β
+ β recordName: "1:modelAs", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: nil, β
+ β count: 42, β
+ β id: 1 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "2", β
+ β recordType: "modelAs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "2:modelAs", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)) β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)), β
+ β count: 1729, β
+ β id: 2 β
+ β ), β
+ β share: CKRecord( β
+ β recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner), β
+ β recordType: "cloudkit.share", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: true, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelBs", β
+ β zoneName: "zone", β
+ β ownerName: "__defaultOwner__", β
+ β recordName: "1:modelBs", β
+ β parentRecordPrimaryKey: "1", β
+ β parentRecordType: "modelAs", β
+ β parentRecordName: "1:modelAs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/zone/__defaultOwner__), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/zone/__defaultOwner__), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__)), β
+ β share: nil, β
+ β id: 1, β
+ β isOn: 0, β
+ β modelAID: 1 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 1 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ """
+ }
+ assertInlineSnapshot(of: container, as: .customDump) {
+ """
+ MockCloudContainer(
+ privateCloudDatabase: MockCloudDatabase(
+ databaseScope: .private,
+ storage: [
+ [0]: CKRecord(
+ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__),
+ recordType: "modelAs",
+ parent: nil,
+ share: nil,
+ count: 42,
+ id: 1
+ ),
+ [1]: CKRecord(
+ recordID: CKRecord.ID(1:modelBs/zone/__defaultOwner__),
+ recordType: "modelBs",
+ parent: CKReference(recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__)),
+ share: nil,
+ id: 1,
+ isOn: 0,
+ modelAID: 1
+ )
+ ]
+ ),
+ sharedCloudDatabase: MockCloudDatabase(
+ databaseScope: .shared,
+ storage: [
+ [0]: CKRecord(
+ recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner),
+ recordType: "cloudkit.share",
+ parent: nil,
+ share: nil
+ ),
+ [1]: CKRecord(
+ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner),
+ recordType: "modelAs",
+ parent: nil,
+ share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)),
+ count: 1729,
+ id: 2
+ )
+ ]
+ )
+ )
+ """
+ }
+ }
+
+ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
+ @Test
+ func movesChildRecordFromPrivateParentToSharedParentWhileSyncEngineStopped() async throws {
+ try await userDatabase.userWrite { db in
+ try db.seed {
+ ModelA.Draft(id: 1, count: 42)
+ ModelB.Draft(id: 1, isOn: true, modelAID: 1)
+ ModelC.Draft(id: 1, title: "Blob", modelBID: 1)
+ }
+ }
+ try await syncEngine.processPendingRecordZoneChanges(scope: .private)
+
+ let externalZone = CKRecordZone(
+ zoneID: CKRecordZone.ID(
+ zoneName: "external.zone",
+ ownerName: "external.owner"
+ )
+ )
+ try await syncEngine.modifyRecordZones(scope: .shared, saving: [externalZone]).notify()
+
+ let modelARecord = CKRecord(
+ recordType: ModelA.tableName,
+ recordID: ModelA.recordID(for: 2, zoneID: externalZone.zoneID)
+ )
+ modelARecord.setValue(2, forKey: "id", at: now)
+ modelARecord.setValue(1729, forKey: "count", at: now)
+ let share = CKShare(
+ rootRecord: modelARecord,
+ shareID: CKRecord.ID(
+ recordName: "share-\(modelARecord.recordID.recordName)",
+ zoneID: modelARecord.recordID.zoneID
+ )
+ )
+ _ = try syncEngine.modifyRecords(scope: .shared, saving: [share, modelARecord])
+ let freshShare = try syncEngine.shared.database.record(for: share.recordID) as! CKShare
+ let freshModelARecord = try syncEngine.shared.database.record(for: modelARecord.recordID)
+
+ try await syncEngine
+ .acceptShare(
+ metadata: ShareMetadata(
+ containerIdentifier: container.containerIdentifier!,
+ hierarchicalRootRecordID: freshModelARecord.recordID,
+ rootRecord: freshModelARecord,
+ share: freshShare
+ )
+ )
+
+ syncEngine.stop()
+
+ try await withDependencies {
+ $0.currentTime.now += 1
+ } operation: {
+ try await self.userDatabase.userWrite { db in
+ try ModelB.find(1).update { $0.modelAID = 2 }.execute(db)
+ }
+ }
+
+ try await syncEngine.start()
+ try await syncEngine.processPendingRecordZoneChanges(scope: .private)
+ try await syncEngine.processPendingRecordZoneChanges(scope: .shared)
+
+ assertQuery(ModelB.all, database: userDatabase.database) {
+ """
+ βββββββββββββββββ
+ β ModelB( β
+ β id: 1, β
+ β isOn: true, β
+ β modelAID: 2 β
+ β ) β
+ βββββββββββββββββ
+ """
+ }
+ assertQuery(ModelC.all, database: userDatabase.database) {
+ """
+ ββββββββββββββββββββ
+ β ModelC( β
+ β id: 1, β
+ β title: "Blob", β
+ β modelBID: 1 β
+ β ) β
+ ββββββββββββββββββββ
+ """
+ }
+ assertQuery(
+ SyncMetadata.order { ($0.recordType, $0.recordName) },
+ database: syncEngine.metadatabase
+ ) {
+ """
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelAs", β
+ β zoneName: "zone", β
+ β ownerName: "__defaultOwner__", β
+ β recordName: "1:modelAs", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: nil, β
+ β count: 42, β
+ β id: 1 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "2", β
+ β recordType: "modelAs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "2:modelAs", β
+ β parentRecordPrimaryKey: nil, β
+ β parentRecordType: nil, β
+ β parentRecordName: nil, β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)) β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(2:modelAs/external.zone/external.owner), β
+ β recordType: "modelAs", β
+ β parent: nil, β
+ β share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)), β
+ β count: 1729, β
+ β id: 2 β
+ β ), β
+ β share: CKRecord( β
+ β recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner), β
+ β recordType: "cloudkit.share", β
+ β parent: nil, β
+ β share: nil β
+ β ), β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: true, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelBs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:modelBs", β
+ β parentRecordPrimaryKey: "2", β
+ β parentRecordType: "modelAs", β
+ β parentRecordName: "2:modelAs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), β
+ β recordType: "modelBs", β
+ β parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β isOn: 1, β
+ β modelAID: 2 β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 1 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
+ β SyncMetadata( β
+ β recordPrimaryKey: "1", β
+ β recordType: "modelCs", β
+ β zoneName: "external.zone", β
+ β ownerName: "external.owner", β
+ β recordName: "1:modelCs", β
+ β parentRecordPrimaryKey: "1", β
+ β parentRecordType: "modelBs", β
+ β parentRecordName: "1:modelBs", β
+ β lastKnownServerRecord: CKRecord( β
+ β recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), β
+ β recordType: "modelCs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)), β
+ β share: nil β
+ β ), β
+ β _lastKnownServerRecordAllFields: CKRecord( β
+ β recordID: CKRecord.ID(1:modelCs/external.zone/external.owner), β
+ β recordType: "modelCs", β
+ β parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)), β
+ β share: nil, β
+ β id: 1, β
+ β modelBID: 1, β
+ β title: "Blob" β
+ β ), β
+ β share: nil, β
+ β _isDeleted: false, β
+ β hasLastKnownServerRecord: true, β
+ β isShared: false, β
+ β userModificationTime: 0 β
+ β ) β
+ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ """
+ }
+ assertInlineSnapshot(of: container, as: .customDump) {
+ """
+ MockCloudContainer(
+ privateCloudDatabase: MockCloudDatabase(
+ databaseScope: .private,
+ storage: [
+ [0]: CKRecord(
+ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__),
+ recordType: "modelAs",
+ parent: nil,
+ share: nil,
+ count: 42,
+ id: 1
+ )
+ ]
+ ),
+ sharedCloudDatabase: MockCloudDatabase(
+ databaseScope: .shared,
+ storage: [
+ [0]: CKRecord(
+ recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner),
+ recordType: "cloudkit.share",
+ parent: nil,
+ share: nil
+ ),
+ [1]: CKRecord(
+ recordID: CKRecord.ID(2:modelAs/external.zone/external.owner),
+ recordType: "modelAs",
+ parent: nil,
+ share: CKReference(recordID: CKRecord.ID(share-2:modelAs/external.zone/external.owner)),
+ count: 1729,
+ id: 2
+ ),
+ [2]: CKRecord(
+ recordID: CKRecord.ID(1:modelBs/external.zone/external.owner),
+ recordType: "modelBs",
+ parent: CKReference(recordID: CKRecord.ID(2:modelAs/external.zone/external.owner)),
+ share: nil,
+ id: 1,
+ isOn: 1,
+ modelAID: 2
+ ),
+ [3]: CKRecord(
+ recordID: CKRecord.ID(1:modelCs/external.zone/external.owner),
+ recordType: "modelCs",
+ parent: CKReference(recordID: CKRecord.ID(1:modelBs/external.zone/external.owner)),
+ share: nil,
+ id: 1,
+ modelBID: 1,
+ title: "Blob"
)
]
)
diff --git a/Tests/SQLiteDataTests/CloudKitTests/TriggerTests.swift b/Tests/SQLiteDataTests/CloudKitTests/TriggerTests.swift
index 13410a6c..d7ef5e19 100644
--- a/Tests/SQLiteDataTests/CloudKitTests/TriggerTests.swift
+++ b/Tests/SQLiteDataTests/CloudKitTests/TriggerTests.swift
@@ -19,78 +19,6 @@
#"""
[
[0]: """
- CREATE TRIGGER "after_delete_on_sqlitedata_icloud_metadata"
- AFTER UPDATE OF "_isDeleted" ON "sqlitedata_icloud_metadata"
- FOR EACH ROW WHEN ((NOT ("old"."_isDeleted") AND "new"."_isDeleted") AND NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) BEGIN
- SELECT "sqlitedata_icloud_didDelete"("new"."recordName", coalesce("new"."lastKnownServerRecord", (
- WITH "ancestorMetadatas" AS (
- SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."lastKnownServerRecord" AS "lastKnownServerRecord"
- FROM "sqlitedata_icloud_metadata"
- WHERE ("sqlitedata_icloud_metadata"."recordName" = "new"."recordName")
- UNION ALL
- SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."lastKnownServerRecord" AS "lastKnownServerRecord"
- FROM "sqlitedata_icloud_metadata"
- JOIN "ancestorMetadatas" ON ("sqlitedata_icloud_metadata"."recordName" IS "ancestorMetadatas"."parentRecordName")
- )
- SELECT "ancestorMetadatas"."lastKnownServerRecord"
- FROM "ancestorMetadatas"
- WHERE ("ancestorMetadatas"."parentRecordName" IS NULL)
- )), "new"."share");
- END
- """,
- [1]: """
- CREATE TRIGGER "after_insert_on_sqlitedata_icloud_metadata"
- AFTER INSERT ON "sqlitedata_icloud_metadata"
- FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
- SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.invalid-record-name-error')
- WHERE NOT (((substr("new"."recordName", 1, 1) <> '_') AND (octet_length("new"."recordName") <= 255)) AND (octet_length("new"."recordName") = length("new"."recordName")));
- SELECT "sqlitedata_icloud_didUpdate"("new"."recordName", coalesce("new"."lastKnownServerRecord", (
- WITH "ancestorMetadatas" AS (
- SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."lastKnownServerRecord" AS "lastKnownServerRecord"
- FROM "sqlitedata_icloud_metadata"
- WHERE ("sqlitedata_icloud_metadata"."recordName" = "new"."recordName")
- UNION ALL
- SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."lastKnownServerRecord" AS "lastKnownServerRecord"
- FROM "sqlitedata_icloud_metadata"
- JOIN "ancestorMetadatas" ON ("sqlitedata_icloud_metadata"."recordName" IS "ancestorMetadatas"."parentRecordName")
- )
- SELECT "ancestorMetadatas"."lastKnownServerRecord"
- FROM "ancestorMetadatas"
- WHERE ("ancestorMetadatas"."parentRecordName" IS NULL)
- )), (
- SELECT "sqlitedata_icloud_metadata"."lastKnownServerRecord"
- FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" IS "new"."parentRecordPrimaryKey") AND ("sqlitedata_icloud_metadata"."recordType" IS "new"."parentRecordType"))
- ), "new"."parentRecordPrimaryKey", "new"."parentRecordType");
- END
- """,
- [2]: """
- CREATE TRIGGER "after_update_on_sqlitedata_icloud_metadata"
- AFTER UPDATE ON "sqlitedata_icloud_metadata"
- FOR EACH ROW WHEN (("old"."_isDeleted" = "new"."_isDeleted") AND NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) BEGIN
- SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.invalid-record-name-error')
- WHERE NOT (((substr("new"."recordName", 1, 1) <> '_') AND (octet_length("new"."recordName") <= 255)) AND (octet_length("new"."recordName") = length("new"."recordName")));
- SELECT "sqlitedata_icloud_didUpdate"("new"."recordName", coalesce("new"."lastKnownServerRecord", (
- WITH "ancestorMetadatas" AS (
- SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."lastKnownServerRecord" AS "lastKnownServerRecord"
- FROM "sqlitedata_icloud_metadata"
- WHERE ("sqlitedata_icloud_metadata"."recordName" = "new"."recordName")
- UNION ALL
- SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."lastKnownServerRecord" AS "lastKnownServerRecord"
- FROM "sqlitedata_icloud_metadata"
- JOIN "ancestorMetadatas" ON ("sqlitedata_icloud_metadata"."recordName" IS "ancestorMetadatas"."parentRecordName")
- )
- SELECT "ancestorMetadatas"."lastKnownServerRecord"
- FROM "ancestorMetadatas"
- WHERE ("ancestorMetadatas"."parentRecordName" IS NULL)
- )), (
- SELECT "sqlitedata_icloud_metadata"."lastKnownServerRecord"
- FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" IS "new"."parentRecordPrimaryKey") AND ("sqlitedata_icloud_metadata"."recordType" IS "new"."parentRecordType"))
- ), "new"."parentRecordPrimaryKey", "new"."parentRecordType");
- END
- """,
- [3]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_childWithOnDeleteSetDefaults_from_sync_engine"
AFTER DELETE ON "childWithOnDeleteSetDefaults"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -98,7 +26,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'childWithOnDeleteSetDefaults'));
END
""",
- [4]: """
+ [1]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_childWithOnDeleteSetDefaults_from_user"
AFTER DELETE ON "childWithOnDeleteSetDefaults"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -119,7 +47,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'childWithOnDeleteSetDefaults'));
END
""",
- [5]: """
+ [2]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_childWithOnDeleteSetNulls_from_sync_engine"
AFTER DELETE ON "childWithOnDeleteSetNulls"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -127,7 +55,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'childWithOnDeleteSetNulls'));
END
""",
- [6]: """
+ [3]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_childWithOnDeleteSetNulls_from_user"
AFTER DELETE ON "childWithOnDeleteSetNulls"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -148,7 +76,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'childWithOnDeleteSetNulls'));
END
""",
- [7]: """
+ [4]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_modelAs_from_sync_engine"
AFTER DELETE ON "modelAs"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -156,7 +84,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs'));
END
""",
- [8]: """
+ [5]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_modelAs_from_user"
AFTER DELETE ON "modelAs"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -177,7 +105,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs'));
END
""",
- [9]: """
+ [6]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_modelBs_from_sync_engine"
AFTER DELETE ON "modelBs"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -185,7 +113,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs'));
END
""",
- [10]: """
+ [7]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_modelBs_from_user"
AFTER DELETE ON "modelBs"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -206,7 +134,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs'));
END
""",
- [11]: """
+ [8]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_modelCs_from_sync_engine"
AFTER DELETE ON "modelCs"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -214,7 +142,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelCs'));
END
""",
- [12]: """
+ [9]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_modelCs_from_user"
AFTER DELETE ON "modelCs"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -235,7 +163,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelCs'));
END
""",
- [13]: """
+ [10]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_parents_from_sync_engine"
AFTER DELETE ON "parents"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -243,7 +171,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'));
END
""",
- [14]: """
+ [11]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_parents_from_user"
AFTER DELETE ON "parents"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -264,7 +192,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'));
END
""",
- [15]: """
+ [12]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_reminderTags_from_sync_engine"
AFTER DELETE ON "reminderTags"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -272,7 +200,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'reminderTags'));
END
""",
- [16]: """
+ [13]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_reminderTags_from_user"
AFTER DELETE ON "reminderTags"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -293,7 +221,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'reminderTags'));
END
""",
- [17]: """
+ [14]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_remindersListAssets_from_sync_engine"
AFTER DELETE ON "remindersListAssets"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -301,7 +229,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersListAssets'));
END
""",
- [18]: """
+ [15]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_remindersListAssets_from_user"
AFTER DELETE ON "remindersListAssets"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -322,7 +250,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersListAssets'));
END
""",
- [19]: """
+ [16]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_remindersListPrivates_from_sync_engine"
AFTER DELETE ON "remindersListPrivates"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -330,7 +258,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersListPrivates'));
END
""",
- [20]: """
+ [17]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_remindersListPrivates_from_user"
AFTER DELETE ON "remindersListPrivates"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -351,7 +279,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersListPrivates'));
END
""",
- [21]: """
+ [18]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_remindersLists_from_sync_engine"
AFTER DELETE ON "remindersLists"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -359,7 +287,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'));
END
""",
- [22]: """
+ [19]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_remindersLists_from_user"
AFTER DELETE ON "remindersLists"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -380,7 +308,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'));
END
""",
- [23]: """
+ [20]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_reminders_from_sync_engine"
AFTER DELETE ON "reminders"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -388,7 +316,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'reminders'));
END
""",
- [24]: """
+ [21]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_reminders_from_user"
AFTER DELETE ON "reminders"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -409,7 +337,27 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'reminders'));
END
""",
- [25]: """
+ [22]: """
+ CREATE TRIGGER "sqlitedata_icloud_after_delete_on_sqlitedata_icloud_metadata"
+ AFTER UPDATE OF "_isDeleted" ON "sqlitedata_icloud_metadata"
+ FOR EACH ROW WHEN ((NOT ("old"."_isDeleted") AND "new"."_isDeleted") AND NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) BEGIN
+ SELECT "sqlitedata_icloud_didDelete"("new"."recordName", coalesce("new"."lastKnownServerRecord", (
+ WITH "ancestorMetadatas" AS (
+ SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."lastKnownServerRecord" AS "lastKnownServerRecord"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE ("sqlitedata_icloud_metadata"."recordName" = "new"."recordName")
+ UNION ALL
+ SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."lastKnownServerRecord" AS "lastKnownServerRecord"
+ FROM "sqlitedata_icloud_metadata"
+ JOIN "ancestorMetadatas" ON ("sqlitedata_icloud_metadata"."recordName" IS "ancestorMetadatas"."parentRecordName")
+ )
+ SELECT "ancestorMetadatas"."lastKnownServerRecord"
+ FROM "ancestorMetadatas"
+ WHERE ("ancestorMetadatas"."parentRecordName" IS NULL)
+ )), "new"."share");
+ END
+ """,
+ [23]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_tags_from_sync_engine"
AFTER DELETE ON "tags"
FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN
@@ -417,7 +365,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."title") AND ("sqlitedata_icloud_metadata"."recordType" = 'tags'));
END
""",
- [26]: """
+ [24]: """
CREATE TRIGGER "sqlitedata_icloud_after_delete_on_tags_from_user"
AFTER DELETE ON "tags"
FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
@@ -438,7 +386,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."title") AND ("sqlitedata_icloud_metadata"."recordType" = 'tags'));
END
""",
- [27]: """
+ [25]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_childWithOnDeleteSetDefaults"
AFTER INSERT ON "childWithOnDeleteSetDefaults"
FOR EACH ROW BEGIN
@@ -456,16 +404,15 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'childWithOnDeleteSetDefaults', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'childWithOnDeleteSetDefaults', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'))), '__defaultOwner__'), "new"."parentID", 'parents'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), '__defaultOwner__'), "new"."parentID", 'parents'
+ ON CONFLICT DO NOTHING;
END
""",
- [28]: """
+ [26]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_childWithOnDeleteSetNulls"
AFTER INSERT ON "childWithOnDeleteSetNulls"
FOR EACH ROW BEGIN
@@ -483,16 +430,15 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'childWithOnDeleteSetNulls', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'childWithOnDeleteSetNulls', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'))), '__defaultOwner__'), "new"."parentID", 'parents'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), '__defaultOwner__'), "new"."parentID", 'parents'
+ ON CONFLICT DO NOTHING;
END
""",
- [29]: """
+ [27]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_modelAs"
AFTER INSERT ON "modelAs"
FOR EACH ROW BEGIN
@@ -510,12 +456,11 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'modelAs', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."id", 'modelAs', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
END
""",
- [30]: """
+ [28]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_modelBs"
AFTER INSERT ON "modelBs"
FOR EACH ROW BEGIN
@@ -533,16 +478,15 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'modelBs', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'modelBs', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs'))), '__defaultOwner__'), "new"."modelAID", 'modelAs'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs')))), '__defaultOwner__'), "new"."modelAID", 'modelAs'
+ ON CONFLICT DO NOTHING;
END
""",
- [31]: """
+ [29]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_modelCs"
AFTER INSERT ON "modelCs"
FOR EACH ROW BEGIN
@@ -560,16 +504,15 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'modelCs', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'modelCs', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs'))), '__defaultOwner__'), "new"."modelBID", 'modelBs'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs')))), '__defaultOwner__'), "new"."modelBID", 'modelBs'
+ ON CONFLICT DO NOTHING;
END
""",
- [32]: """
+ [30]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_parents"
AFTER INSERT ON "parents"
FOR EACH ROW BEGIN
@@ -587,12 +530,11 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'parents', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."id", 'parents', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
END
""",
- [33]: """
+ [31]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_reminderTags"
AFTER INSERT ON "reminderTags"
FOR EACH ROW BEGIN
@@ -610,12 +552,11 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'reminderTags', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."id", 'reminderTags', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
END
""",
- [34]: """
+ [32]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_reminders"
AFTER INSERT ON "reminders"
FOR EACH ROW BEGIN
@@ -633,16 +574,15 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'reminders', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'reminders', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
+ ON CONFLICT DO NOTHING;
END
""",
- [35]: """
+ [33]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_remindersListAssets"
AFTER INSERT ON "remindersListAssets"
FOR EACH ROW BEGIN
@@ -660,16 +600,15 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'remindersListAssets', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'remindersListAssets', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
+ ON CONFLICT DO NOTHING;
END
""",
- [36]: """
+ [34]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_remindersListPrivates"
AFTER INSERT ON "remindersListPrivates"
FOR EACH ROW BEGIN
@@ -687,16 +626,15 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'remindersListPrivates', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'remindersListPrivates', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
+ ON CONFLICT DO NOTHING;
END
""",
- [37]: """
+ [35]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_remindersLists"
AFTER INSERT ON "remindersLists"
FOR EACH ROW BEGIN
@@ -714,12 +652,20 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'remindersLists', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."id", 'remindersLists', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
END
""",
- [38]: """
+ [36]: """
+ CREATE TRIGGER "sqlitedata_icloud_after_insert_on_sqlitedata_icloud_metadata"
+ AFTER INSERT ON "sqlitedata_icloud_metadata"
+ FOR EACH ROW WHEN NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) BEGIN
+ SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.invalid-record-name-error')
+ WHERE NOT (((substr("new"."recordName", 1, 1) <> '_') AND (octet_length("new"."recordName") <= 255)) AND (octet_length("new"."recordName") = length("new"."recordName")));
+ SELECT "sqlitedata_icloud_didUpdate"("new"."recordName", "new"."zoneName", "new"."ownerName", "new"."zoneName", "new"."ownerName", NULL);
+ END
+ """,
+ [37]: """
CREATE TRIGGER "sqlitedata_icloud_after_insert_on_tags"
AFTER INSERT ON "tags"
FOR EACH ROW BEGIN
@@ -737,12 +683,11 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."title", 'tags', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."title", 'tags', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
END
""",
- [39]: """
+ [38]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_childWithOnDeleteSetDefaults"
AFTER UPDATE OF "id" ON "childWithOnDeleteSetDefaults"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -763,7 +708,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'childWithOnDeleteSetDefaults'));
END
""",
- [40]: """
+ [39]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_childWithOnDeleteSetNulls"
AFTER UPDATE OF "id" ON "childWithOnDeleteSetNulls"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -784,7 +729,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'childWithOnDeleteSetNulls'));
END
""",
- [41]: """
+ [40]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_modelAs"
AFTER UPDATE OF "id" ON "modelAs"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -805,7 +750,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs'));
END
""",
- [42]: """
+ [41]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_modelBs"
AFTER UPDATE OF "id" ON "modelBs"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -826,7 +771,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs'));
END
""",
- [43]: """
+ [42]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_modelCs"
AFTER UPDATE OF "id" ON "modelCs"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -847,7 +792,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelCs'));
END
""",
- [44]: """
+ [43]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_parents"
AFTER UPDATE OF "id" ON "parents"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -868,7 +813,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'));
END
""",
- [45]: """
+ [44]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_reminderTags"
AFTER UPDATE OF "id" ON "reminderTags"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -889,7 +834,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'reminderTags'));
END
""",
- [46]: """
+ [45]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_reminders"
AFTER UPDATE OF "id" ON "reminders"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -910,7 +855,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'reminders'));
END
""",
- [47]: """
+ [46]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_remindersListAssets"
AFTER UPDATE OF "id" ON "remindersListAssets"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -931,7 +876,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersListAssets'));
END
""",
- [48]: """
+ [47]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_remindersListPrivates"
AFTER UPDATE OF "id" ON "remindersListPrivates"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -952,7 +897,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersListPrivates'));
END
""",
- [49]: """
+ [48]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_remindersLists"
AFTER UPDATE OF "id" ON "remindersLists"
FOR EACH ROW WHEN ("old"."id" <> "new"."id") BEGIN
@@ -973,7 +918,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'));
END
""",
- [50]: """
+ [49]: """
CREATE TRIGGER "sqlitedata_icloud_after_primary_key_change_on_tags"
AFTER UPDATE OF "title" ON "tags"
FOR EACH ROW WHEN ("old"."title" <> "new"."title") BEGIN
@@ -994,7 +939,7 @@
WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "old"."title") AND ("sqlitedata_icloud_metadata"."recordType" = 'tags'));
END
""",
- [51]: """
+ [50]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_childWithOnDeleteSetDefaults"
AFTER UPDATE ON "childWithOnDeleteSetDefaults"
FOR EACH ROW BEGIN
@@ -1012,16 +957,22 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'childWithOnDeleteSetDefaults', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'childWithOnDeleteSetDefaults', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'))), '__defaultOwner__'), "new"."parentID", 'parents'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), '__defaultOwner__'), "new"."parentID", 'parents'
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = "new"."parentID", "parentRecordType" = 'parents', "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'childWithOnDeleteSetDefaults'));
END
""",
- [52]: """
+ [51]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_childWithOnDeleteSetNulls"
AFTER UPDATE ON "childWithOnDeleteSetNulls"
FOR EACH ROW BEGIN
@@ -1039,16 +990,22 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'childWithOnDeleteSetNulls', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'childWithOnDeleteSetNulls', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), '__defaultOwner__'), "new"."parentID", 'parents'
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'))), '__defaultOwner__'), "new"."parentID", 'parents'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."parentID") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents')))), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = "new"."parentID", "parentRecordType" = 'parents', "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'childWithOnDeleteSetNulls'));
END
""",
- [53]: """
+ [52]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_modelAs"
AFTER UPDATE ON "modelAs"
FOR EACH ROW BEGIN
@@ -1066,12 +1023,14 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'modelAs', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."id", 'modelAs', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce("sqlitedata_icloud_currentZoneName"(), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce("sqlitedata_icloud_currentOwnerName"(), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = NULL, "parentRecordType" = NULL, "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs'));
END
""",
- [54]: """
+ [53]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_modelBs"
AFTER UPDATE ON "modelBs"
FOR EACH ROW BEGIN
@@ -1089,16 +1048,22 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'modelBs', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'modelBs', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs')))), '__defaultOwner__'), "new"."modelAID", 'modelAs'
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs'))), '__defaultOwner__'), "new"."modelAID", 'modelAs'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelAID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelAs')))), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = "new"."modelAID", "parentRecordType" = 'modelAs', "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs'));
END
""",
- [55]: """
+ [54]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_modelCs"
AFTER UPDATE ON "modelCs"
FOR EACH ROW BEGIN
@@ -1116,16 +1081,22 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'modelCs', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'modelCs', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs')))), '__defaultOwner__'), "new"."modelBID", 'modelBs'
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs'))), '__defaultOwner__'), "new"."modelBID", 'modelBs'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."modelBID") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelBs')))), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = "new"."modelBID", "parentRecordType" = 'modelBs', "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'modelCs'));
END
""",
- [56]: """
+ [55]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_parents"
AFTER UPDATE ON "parents"
FOR EACH ROW BEGIN
@@ -1143,12 +1114,14 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'parents', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."id", 'parents', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce("sqlitedata_icloud_currentZoneName"(), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce("sqlitedata_icloud_currentOwnerName"(), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = NULL, "parentRecordType" = NULL, "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'parents'));
END
""",
- [57]: """
+ [56]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_reminderTags"
AFTER UPDATE ON "reminderTags"
FOR EACH ROW BEGIN
@@ -1166,12 +1139,14 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'reminderTags', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."id", 'reminderTags', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce("sqlitedata_icloud_currentZoneName"(), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce("sqlitedata_icloud_currentOwnerName"(), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = NULL, "parentRecordType" = NULL, "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'reminderTags'));
END
""",
- [58]: """
+ [57]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_reminders"
AFTER UPDATE ON "reminders"
FOR EACH ROW BEGIN
@@ -1189,16 +1164,22 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'reminders', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'reminders', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = "new"."remindersListID", "parentRecordType" = 'remindersLists', "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'reminders'));
END
""",
- [59]: """
+ [58]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_remindersListAssets"
AFTER UPDATE ON "remindersListAssets"
FOR EACH ROW BEGIN
@@ -1216,16 +1197,22 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'remindersListAssets', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'remindersListAssets', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = "new"."remindersListID", "parentRecordType" = 'remindersLists', "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersListAssets'));
END
""",
- [60]: """
+ [59]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_remindersListPrivates"
AFTER UPDATE ON "remindersListPrivates"
FOR EACH ROW BEGIN
@@ -1243,16 +1230,22 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'remindersListPrivates', coalesce((SELECT "sqlitedata_icloud_metadata"."zoneName"
+ SELECT "new"."id", 'remindersListPrivates', coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), 'zone'), coalesce((SELECT "sqlitedata_icloud_metadata"."ownerName"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), 'zone'), coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
FROM "sqlitedata_icloud_metadata"
- WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists'
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce(coalesce("sqlitedata_icloud_currentZoneName"(), (SELECT "sqlitedata_icloud_metadata"."zoneName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce("sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."remindersListID") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists')))), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = "new"."remindersListID", "parentRecordType" = 'remindersLists', "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersListPrivates'));
END
""",
- [61]: """
+ [60]: """
CREATE TRIGGER "sqlitedata_icloud_after_update_on_remindersLists"
AFTER UPDATE ON "remindersLists"
FOR EACH ROW BEGIN
@@ -1270,9 +1263,33 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."id", 'remindersLists', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."id", 'remindersLists', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce("sqlitedata_icloud_currentZoneName"(), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce("sqlitedata_icloud_currentOwnerName"(), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = NULL, "parentRecordType" = NULL, "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."id") AND ("sqlitedata_icloud_metadata"."recordType" = 'remindersLists'));
+ END
+ """,
+ [61]: """
+ CREATE TRIGGER "sqlitedata_icloud_after_update_on_sqlitedata_icloud_metadata"
+ AFTER UPDATE ON "sqlitedata_icloud_metadata"
+ FOR EACH ROW WHEN (("old"."_isDeleted" = "new"."_isDeleted") AND NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) BEGIN
+ SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.invalid-record-name-error')
+ WHERE NOT (((substr("new"."recordName", 1, 1) <> '_') AND (octet_length("new"."recordName") <= 255)) AND (octet_length("new"."recordName") = length("new"."recordName")));
+ SELECT "sqlitedata_icloud_didUpdate"("new"."recordName", "new"."zoneName", "new"."ownerName", "old"."zoneName", "old"."ownerName", CASE WHEN (("new"."zoneName" <> "old"."zoneName") OR ("new"."ownerName" <> "old"."ownerName")) THEN (
+ WITH "descendantMetadatas" AS (
+ SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", NULL AS "parentRecordName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE ("sqlitedata_icloud_metadata"."recordName" = "new"."recordName")
+ UNION ALL
+ SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName"
+ FROM "sqlitedata_icloud_metadata"
+ JOIN "descendantMetadatas" ON ("sqlitedata_icloud_metadata"."parentRecordName" = "descendantMetadatas"."recordName")
+ )
+ SELECT json_group_array("descendantMetadatas"."recordName")
+ FROM "descendantMetadatas"
+ WHERE ("descendantMetadatas"."recordName" <> "new"."recordName")
+ ) END);
END
""",
[62]: """
@@ -1293,9 +1310,30 @@
WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"()) AND ("rootShares"."parentRecordName" IS NULL)) AND NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")));
INSERT INTO "sqlitedata_icloud_metadata"
("recordPrimaryKey", "recordType", "zoneName", "ownerName", "parentRecordPrimaryKey", "parentRecordType")
- SELECT "new"."title", 'tags', 'zone', '__defaultOwner__', NULL, NULL
- ON CONFLICT ("recordPrimaryKey", "recordType")
- DO UPDATE SET "parentRecordPrimaryKey" = "excluded"."parentRecordPrimaryKey", "parentRecordType" = "excluded"."parentRecordType", "userModificationTime" = "excluded"."userModificationTime";
+ SELECT "new"."title", 'tags', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL
+ ON CONFLICT DO NOTHING;
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = coalesce("sqlitedata_icloud_currentZoneName"(), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce("sqlitedata_icloud_currentOwnerName"(), "sqlitedata_icloud_metadata"."ownerName"), "parentRecordPrimaryKey" = NULL, "parentRecordType" = NULL, "userModificationTime" = "sqlitedata_icloud_currentTime"()
+ WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey" = "new"."title") AND ("sqlitedata_icloud_metadata"."recordType" = 'tags'));
+ END
+ """,
+ [63]: """
+ CREATE TRIGGER "sqlitedata_icloud_after_zone_update_on_sqlitedata_icloud_metadata"
+ AFTER UPDATE OF "zoneName", "ownerName" ON "sqlitedata_icloud_metadata"
+ FOR EACH ROW WHEN (("new"."zoneName" <> "old"."zoneName") OR ("new"."ownerName" <> "old"."ownerName")) BEGIN
+ UPDATE "sqlitedata_icloud_metadata"
+ SET "zoneName" = "new"."zoneName", "ownerName" = "new"."ownerName", "lastKnownServerRecord" = NULL, "_lastKnownServerRecordAllFields" = NULL
+ WHERE ("sqlitedata_icloud_metadata"."recordName" IN (WITH "descendantMetadatas" AS (
+ SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", NULL AS "parentRecordName"
+ FROM "sqlitedata_icloud_metadata"
+ WHERE ("sqlitedata_icloud_metadata"."recordName" = "new"."recordName")
+ UNION ALL
+ SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName"
+ FROM "sqlitedata_icloud_metadata"
+ JOIN "descendantMetadatas" ON ("sqlitedata_icloud_metadata"."parentRecordName" = "descendantMetadatas"."recordName")
+ )
+ SELECT "descendantMetadatas"."recordName"
+ FROM "descendantMetadatas"));
END
"""
]
diff --git a/Tests/SQLiteDataTests/Internal/BaseCloudKitTests.swift b/Tests/SQLiteDataTests/Internal/BaseCloudKitTests.swift
index 5e34de4e..ba37e57b 100644
--- a/Tests/SQLiteDataTests/Internal/BaseCloudKitTests.swift
+++ b/Tests/SQLiteDataTests/Internal/BaseCloudKitTests.swift
@@ -7,7 +7,7 @@ import Testing
import os
@Suite(
- .snapshots(record: .missing),
+ .snapshots(record: .failed),
.dependencies {
$0.currentTime.now = 0
$0.dataManager = InMemoryDataManager()
diff --git a/Tests/SQLiteDataTests/Internal/PrintTimestampsScope.swift b/Tests/SQLiteDataTests/Internal/PrintTimestampsScope.swift
index f300124c..067815c6 100644
--- a/Tests/SQLiteDataTests/Internal/PrintTimestampsScope.swift
+++ b/Tests/SQLiteDataTests/Internal/PrintTimestampsScope.swift
@@ -20,9 +20,9 @@
}
extension Trait where Self == _PrintTimestampsScope {
- static var printTimestamps: Self { .init() }
+ static var printTimestamps: Self { Self() }
static func printTimestamps(_ printTimestamps: Bool) -> Self {
- .init(printTimestamps)
+ Self(printTimestamps)
}
}
#endif
diff --git a/Tests/SQLiteDataTests/Internal/Schema.swift b/Tests/SQLiteDataTests/Internal/Schema.swift
index 92614e21..3d11f0a7 100644
--- a/Tests/SQLiteDataTests/Internal/Schema.swift
+++ b/Tests/SQLiteDataTests/Internal/Schema.swift
@@ -82,6 +82,9 @@ func database(
if attachMetadatabase {
try db.attachMetadatabase(containerIdentifier: containerIdentifier)
}
+ // db.trace {
+ // print($0.expandedDescription)
+ // }
}
let url = URL.temporaryDirectory.appending(path: "\(UUID().uuidString).sqlite")
let database = try DatabasePool(path: url.path(), configuration: configuration)
diff --git a/Tests/SQLiteDataTests/Internal/TestScopes.swift b/Tests/SQLiteDataTests/Internal/TestScopes.swift
index 42ab482d..3608458b 100644
--- a/Tests/SQLiteDataTests/Internal/TestScopes.swift
+++ b/Tests/SQLiteDataTests/Internal/TestScopes.swift
@@ -25,7 +25,7 @@
static func prepareDatabase(
_ prepareDatabase: @escaping @Sendable (UserDatabase) async throws -> Void
) -> Self {
- .init(prepareDatabase: prepareDatabase)
+ Self(prepareDatabase: prepareDatabase)
}
}
@@ -48,7 +48,7 @@
extension Trait where Self == _StartImmediatelyTrait {
static func startImmediately(_ startImmediately: Bool) -> Self {
- .init(startImmediately: startImmediately)
+ Self(startImmediately: startImmediately)
}
}
@@ -70,9 +70,9 @@
}
extension Trait where Self == _AttachMetadatabaseTrait {
- static var attachMetadatabase: Self { .init(attachMetadatabase: true) }
+ static var attachMetadatabase: Self { Self(attachMetadatabase: true) }
static func attachMetadatabase(_ attachMetadatabase: Bool) -> Self {
- .init(attachMetadatabase: attachMetadatabase)
+ Self(attachMetadatabase: attachMetadatabase)
}
}
@@ -96,9 +96,9 @@
}
extension Trait where Self == _AccountStatusScope {
- static var accountStatus: Self { .init() }
+ static var accountStatus: Self { Self() }
static func accountStatus(_ accountStatus: CKAccountStatus) -> Self {
- .init(accountStatus)
+ Self(accountStatus)
}
}
#endif