diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..04f178c7 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(swift --version:*)", + "Bash(~/.swiftly/bin/swiftly list:*)", + "Bash(~/.swiftly/bin/swiftly use:*)" + ] + } +} diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 00000000..8452b0f2 --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,57 @@ +name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize] + # Optional: Only run on specific file changes + # paths: + # - "src/**/*.ts" + # - "src/**/*.tsx" + # - "src/**/*.js" + # - "src/**/*.jsx" + +jobs: + claude-review: + # Optional: Filter by PR author + # if: | + # github.event.pull_request.user.login == 'external-contributor' || + # github.event.pull_request.user.login == 'new-developer' || + # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + prompt: | + REPO: ${{ github.repository }} + PR NUMBER: ${{ github.event.pull_request.number }} + + Please review this pull request and provide feedback on: + - Code quality and best practices + - Potential bugs or issues + - Performance considerations + - Security concerns + - Test coverage + + Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback. + + Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR. + + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://code.claude.com/docs/en/cli-reference for available options + claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"' + diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 00000000..d300267f --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,50 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + actions: read # Required for Claude to read CI results on PRs + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read + + # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it. + # prompt: 'Update the pull request description to include a summary of changes.' + + # Optional: Add claude_args to customize behavior and configuration + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://code.claude.com/docs/en/cli-reference for available options + # claude_args: '--allowed-tools Bash(gh pr:*)' + diff --git a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9348435a..c7e269c8 100644 --- a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -123,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-structured-queries", "state" : { - "revision" : "862802b5a66aec04219b7c2a10e06a5681da86ee", - "version" : "0.27.0" + "revision" : "dc29ae126d9767a064202db6afa0b651ba23b7f8", + "version" : "0.29.0" } }, { @@ -136,6 +136,15 @@ "version" : "602.0.0" } }, + { + "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/RemindersTests/Internal.swift b/Examples/RemindersTests/Internal.swift index a73dc220..6d763a8f 100644 --- a/Examples/RemindersTests/Internal.swift +++ b/Examples/RemindersTests/Internal.swift @@ -12,6 +12,7 @@ import Testing .dependency(\.uuid, .incrementing), .dependencies { try $0.bootstrapDatabase() + try await $0.defaultSyncEngine.start() try $0.defaultDatabase.seedSampleData() try await $0.defaultSyncEngine.sendChanges() }, diff --git a/Examples/SyncUpTests/SyncUpFormTests.swift b/Examples/SyncUpTests/SyncUpFormTests.swift index df6b6c24..c0f60e96 100644 --- a/Examples/SyncUpTests/SyncUpFormTests.swift +++ b/Examples/SyncUpTests/SyncUpFormTests.swift @@ -10,6 +10,7 @@ import Testing @Suite( .dependencies { try $0.bootstrapDatabase() + try await $0.defaultSyncEngine.start() try await $0.defaultDatabase.seedForTests() $0.uuid = .incrementing } diff --git a/Package.resolved b/Package.resolved index 6c09d839..91129fac 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,22 +1,22 @@ { - "originHash" : "6cd14013e211dd746d8c9744f0a929fb46d1bd7f15becd1b00ebde3fa03d255a", + "originHash" : "1f54cf001254017fb1a126aa758cb1c8aee347dfe61e50c59ede5d5ed61f62aa", "pins" : [ { "identity" : "combine-schedulers", "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/combine-schedulers", "state" : { - "revision" : "5928286acce13def418ec36d05a001a9641086f2", - "version" : "1.0.3" + "revision" : "fd16d76fd8b9a976d88bfb6cacc05ca8d19c91b6", + "version" : "1.1.0" } }, { "identity" : "grdb.swift", "kind" : "remoteSourceControl", - "location" : "https://github.com/groue/GRDB.swift", + "location" : "https://github.com/doozMen/GRDB.swift", "state" : { - "revision" : "18497b68fdbb3a09528d260a0a0e1e7e61c8c53d", - "version" : "7.8.0" + "branch" : "master", + "revision" : "aa0079aeb82a4bf00324561a40bffe68c6fe1c26" } }, { @@ -94,19 +94,19 @@ { "identity" : "swift-perception", "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-perception", + "location" : "https://github.com/doozMen/swift-perception", "state" : { - "revision" : "4f47ebafed5f0b0172cf5c661454fa8e28fb2ac4", - "version" : "2.0.9" + "branch" : "main", + "revision" : "9237a92716ccbcd4be8c5330ed372f243c9d23d9" } }, { "identity" : "swift-sharing", "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-sharing", + "location" : "https://github.com/doozMen/swift-sharing", "state" : { - "revision" : "3bfc408cc2d0bee2287c174da6b1c76768377818", - "version" : "2.7.4" + "branch" : "main", + "revision" : "a367f93207aa67a7a9953946ae3b8d47d223f6af" } }, { @@ -123,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-structured-queries", "state" : { - "revision" : "862802b5a66aec04219b7c2a10e06a5681da86ee", - "version" : "0.27.0" + "revision" : "d8163b3a98f3c8434c4361e85126db449d84bc66", + "version" : "0.30.0" } }, { @@ -141,8 +141,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", "state" : { - "revision" : "4c27acf5394b645b70d8ba19dc249c0472d5f618", - "version" : "1.7.0" + "revision" : "31073495cae9caf243c440eac94b3ab067e3d7bc", + "version" : "1.8.0" } } ], diff --git a/Package.swift b/Package.swift index 8ac697dc..06522024 100644 --- a/Package.swift +++ b/Package.swift @@ -1,14 +1,11 @@ -// swift-tools-version: 6.1 +// swift-tools-version: 6.2.1 import PackageDescription let package = Package( name: "sqlite-data", platforms: [ - .iOS(.v13), - .macOS(.v10_15), - .tvOS(.v13), - .watchOS(.v7), + .macOS(.v15), ], products: [ .library( @@ -28,16 +25,17 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), - .package(url: "https://github.com/groue/GRDB.swift", from: "7.6.0"), + // NB: Fork synced with upstream v7.9.0 + .package(url: "https://github.com/doozMen/GRDB.swift", branch: "master"), .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"), .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"), - .package(url: "https://github.com/pointfreeco/swift-perception", from: "2.0.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"), + // NB: Fork with Swift 6.3 fixes (uses doozMen/swift-perception) + .package(url: "https://github.com/doozMen/swift-sharing", branch: "main"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"), .package( url: "https://github.com/pointfreeco/swift-structured-queries", - from: "0.27.0", + from: "0.29.0", traits: [ .trait(name: "StructuredQueriesTagged", condition: .when(traits: ["SQLiteDataTagged"])) ] @@ -54,7 +52,6 @@ let package = Package( .product(name: "GRDB", package: "GRDB.swift"), .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), .product(name: "OrderedCollections", package: "swift-collections"), - .product(name: "Perception", package: "swift-perception"), .product(name: "Sharing", package: "swift-sharing"), .product(name: "StructuredQueriesSQLite", package: "swift-structured-queries"), .product( @@ -106,7 +103,8 @@ for index in package.targets.indices { #if !os(Windows) // Add the documentation compiler plugin if possible + // NB: Use explicit type to avoid Swift 6.2.3 circular reference bug package.dependencies.append( - .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") + Package.Dependency.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") ) #endif diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift deleted file mode 100644 index 5ff5be38..00000000 --- a/Package@swift-6.0.swift +++ /dev/null @@ -1,92 +0,0 @@ -// swift-tools-version: 6.0 - -import PackageDescription - -let package = Package( - name: "sqlite-data", - platforms: [ - .iOS(.v13), - .macOS(.v10_15), - .tvOS(.v13), - .watchOS(.v7), - ], - products: [ - .library( - name: "SQLiteData", - targets: ["SQLiteData"] - ), - .library( - name: "SQLiteDataTestSupport", - targets: ["SQLiteDataTestSupport"] - ), - ], - dependencies: [ - .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), - .package(url: "https://github.com/groue/GRDB.swift", from: "7.6.0"), - .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), - .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"), - .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"), - .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"), - .package(url: "https://github.com/pointfreeco/swift-structured-queries", from: "0.27.0"), - .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.5.0"), - ], - targets: [ - .target( - name: "SQLiteData", - dependencies: [ - .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "Dependencies", package: "swift-dependencies"), - .product(name: "GRDB", package: "GRDB.swift"), - .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), - .product(name: "OrderedCollections", package: "swift-collections"), - .product(name: "Sharing", package: "swift-sharing"), - .product(name: "StructuredQueriesSQLite", package: "swift-structured-queries"), - ] - ), - .target( - name: "SQLiteDataTestSupport", - dependencies: [ - "SQLiteData", - .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "CustomDump", package: "swift-custom-dump"), - .product(name: "Dependencies", package: "swift-dependencies"), - .product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"), - .product(name: "StructuredQueriesTestSupport", package: "swift-structured-queries"), - ] - ), - .testTarget( - name: "SQLiteDataTests", - dependencies: [ - "SQLiteData", - "SQLiteDataTestSupport", - .product(name: "DependenciesTestSupport", package: "swift-dependencies"), - .product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"), - .product(name: "SnapshotTestingCustomDump", package: "swift-snapshot-testing"), - .product(name: "StructuredQueries", package: "swift-structured-queries"), - ] - ), - ], - swiftLanguageModes: [.v6] -) - -let swiftSettings: [SwiftSetting] = [ - .enableUpcomingFeature("MemberImportVisibility") - // .unsafeFlags([ - // "-Xfrontend", - // "-warn-long-function-bodies=50", - // "-Xfrontend", - // "-warn-long-expression-type-checking=50", - // ]) -] - -for index in package.targets.indices { - package.targets[index].swiftSettings = swiftSettings -} - -#if !os(Windows) - // Add the documentation compiler plugin if possible - package.dependencies.append( - .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") - ) -#endif diff --git a/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift b/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift index 2c64af7b..998a774a 100644 --- a/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift +++ b/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift @@ -1,4 +1,6 @@ -#if canImport(CloudKit) +// NB: Swift 6.3-dev compiler crashes on the generic `open` function in _update. +// Tracking: https://github.com/doozMen/sqlite-data/issues/2 +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import CryptoKit import StructuredQueriesCore @@ -146,6 +148,10 @@ @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) extension CKRecord { + func hasSet(key: String) -> Bool { + self.encryptedValues["\(CKRecord.userModificationTimeKey)_\(key)"] != nil + } + @discardableResult package func setValue( _ newValue: some CKRecordValueProtocol & Equatable, @@ -233,6 +239,9 @@ encryptedValues[at: key] = userModificationTime self.userModificationTime = userModificationTime return true + } else if !hasSet(key: key) { + encryptedValues[at: key] = userModificationTime + self.userModificationTime = userModificationTime } return false } @@ -283,10 +292,29 @@ typealias EquatableCKRecordValueProtocol = CKRecordValueProtocol & Equatable self.userModificationTime = other.userModificationTime - for column in T.TableColumns.writableColumns { + _update( + with: other, + row: row, + columnNames: &columnNames, + parentForeignKey: parentForeignKey, + columns: T.TableColumns.writableColumns + ) + } + + private func _update( + with other: CKRecord, + row: T, + columnNames: inout [String], + parentForeignKey: ForeignKey?, + columns: [any WritableTableColumnExpression] + ) { + typealias EquatableCKRecordValueProtocol = CKRecordValueProtocol & Equatable + + for column in columns { func open(_ column: some WritableTableColumnExpression) { let key = column.name - let keyPath = column.keyPath as! KeyPath + let column = column as! any WritableTableColumnExpression + let keyPath = column.keyPath let didSet: Bool if let value = other[key] as? CKAsset { didSet = setAsset(value, forKey: key, at: other.encryptedValues[at: key]) diff --git a/Sources/SQLiteData/CloudKit/CloudKitSharing.swift b/Sources/SQLiteData/CloudKit/CloudKitSharing.swift index d36306c8..77b6b767 100644 --- a/Sources/SQLiteData/CloudKit/CloudKitSharing.swift +++ b/Sources/SQLiteData/CloudKit/CloudKitSharing.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import Dependencies import SwiftUI @@ -133,7 +133,9 @@ recordPrimaryKey: record.primaryKey.rawIdentifier, reason: .recordMetadataNotFound, debugDescription: """ - No sync metadata found for record. Has the record been saved to the database? + No sync metadata found for record. Has the record been saved to the database \ + and synchronized to iCloud? Invoke 'SyncEngine.sendChanges()' to force \ + synchronization. """ ) } diff --git a/Sources/SQLiteData/CloudKit/DefaultSyncEngine.swift b/Sources/SQLiteData/CloudKit/DefaultSyncEngine.swift index 9a2c27be..2eaf080a 100644 --- a/Sources/SQLiteData/CloudKit/DefaultSyncEngine.swift +++ b/Sources/SQLiteData/CloudKit/DefaultSyncEngine.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import Dependencies diff --git a/Sources/SQLiteData/CloudKit/Internal/CloudContainer.swift b/Sources/SQLiteData/CloudKit/Internal/CloudContainer.swift index 4829102f..b0cc5191 100644 --- a/Sources/SQLiteData/CloudKit/Internal/CloudContainer.swift +++ b/Sources/SQLiteData/CloudKit/Internal/CloudContainer.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 15, tvOS 15, macOS 12, watchOS 8, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/CloudDatabase.swift b/Sources/SQLiteData/CloudKit/Internal/CloudDatabase.swift index 94a0dc61..76da5142 100644 --- a/Sources/SQLiteData/CloudKit/Internal/CloudDatabase.swift +++ b/Sources/SQLiteData/CloudKit/Internal/CloudDatabase.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit package protocol CloudDatabase: AnyObject, Hashable, Sendable { diff --git a/Sources/SQLiteData/CloudKit/Internal/CloudKitFunctions.swift b/Sources/SQLiteData/CloudKit/Internal/CloudKitFunctions.swift index afab5b52..ccaf636b 100644 --- a/Sources/SQLiteData/CloudKit/Internal/CloudKitFunctions.swift +++ b/Sources/SQLiteData/CloudKit/Internal/CloudKitFunctions.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import Foundation diff --git a/Sources/SQLiteData/CloudKit/Internal/DataManager.swift b/Sources/SQLiteData/CloudKit/Internal/DataManager.swift index 0bf280c4..053f5eac 100644 --- a/Sources/SQLiteData/CloudKit/Internal/DataManager.swift +++ b/Sources/SQLiteData/CloudKit/Internal/DataManager.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) && canImport(CryptoKit) +#if canImport(CloudKit) && canImport(CryptoKit) && !compiler(>=6.3) import CryptoKit import Dependencies import Foundation @@ -77,7 +77,7 @@ } package var temporaryDirectory: URL { - URL(fileURLWithPath: "/") + URL(fileURLWithPath: "/tmp") } } @@ -86,6 +86,9 @@ static var liveValue: any DataManager { LiveDataManager() } + static var previewValue: any DataManager { + InMemoryDataManager() + } static var testValue: any DataManager { InMemoryDataManager() } diff --git a/Sources/SQLiteData/CloudKit/Internal/DatetimeGenerator.swift b/Sources/SQLiteData/CloudKit/Internal/DatetimeGenerator.swift index dd161e50..675babfb 100644 --- a/Sources/SQLiteData/CloudKit/Internal/DatetimeGenerator.swift +++ b/Sources/SQLiteData/CloudKit/Internal/DatetimeGenerator.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Dependencies import Foundation diff --git a/Sources/SQLiteData/CloudKit/Internal/DefaultNotificationCenter.swift b/Sources/SQLiteData/CloudKit/Internal/DefaultNotificationCenter.swift index d1423e4e..3fca7742 100644 --- a/Sources/SQLiteData/CloudKit/Internal/DefaultNotificationCenter.swift +++ b/Sources/SQLiteData/CloudKit/Internal/DefaultNotificationCenter.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) && canImport(UIKit) +#if canImport(CloudKit) && canImport(UIKit) && !compiler(>=6.3) import UIKit private enum DefaultNotificationCenterKey: DependencyKey { diff --git a/Sources/SQLiteData/CloudKit/Internal/ForeignKey.swift b/Sources/SQLiteData/CloudKit/Internal/ForeignKey.swift index ae329bb6..d8bec02e 100644 --- a/Sources/SQLiteData/CloudKit/Internal/ForeignKey.swift +++ b/Sources/SQLiteData/CloudKit/Internal/ForeignKey.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Foundation import StructuredQueriesCore diff --git a/Sources/SQLiteData/CloudKit/Internal/IsolatedWeakVar.swift b/Sources/SQLiteData/CloudKit/Internal/IsolatedWeakVar.swift index 4a17ef04..28674b35 100644 --- a/Sources/SQLiteData/CloudKit/Internal/IsolatedWeakVar.swift +++ b/Sources/SQLiteData/CloudKit/Internal/IsolatedWeakVar.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Foundation final class IsolatedWeakVar: @unchecked Sendable { diff --git a/Sources/SQLiteData/CloudKit/Internal/Logging.swift b/Sources/SQLiteData/CloudKit/Internal/Logging.swift index b7d4b214..d0f7f059 100644 --- a/Sources/SQLiteData/CloudKit/Internal/Logging.swift +++ b/Sources/SQLiteData/CloudKit/Internal/Logging.swift @@ -1,4 +1,4 @@ -#if DEBUG && canImport(CloudKit) +#if DEBUG && canImport(CloudKit) && !compiler(>=6.3) import CloudKit import TabularData import os diff --git a/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift b/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift index c8efa856..230b3c02 100644 --- a/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift +++ b/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Foundation import os diff --git a/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift b/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift index aaf8568b..c92d3d5e 100644 --- a/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift +++ b/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift b/Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift index ae093dd5..f655dde6 100644 --- a/Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift +++ b/Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import IssueReporting @@ -60,7 +60,7 @@ for key in record.allKeys() { guard let assetData = state.assets[AssetID(recordID: record.recordID, key: key)] else { continue } - let url = URL(filePath: UUID().uuidString.lowercased()) + let url = dataManager.wrappedValue.temporaryDirectory.appending(path: UUID().uuidString) try dataManager.wrappedValue.save(assetData, to: url) record[key] = CKAsset(fileURL: url) } diff --git a/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift b/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift index b30f3390..1f4faba7 100644 --- a/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift +++ b/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import IssueReporting import OrderedCollections @@ -199,7 +199,14 @@ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) extension SyncEngine { - package func processPendingRecordZoneChanges( + package struct SendRecordsCallback { + fileprivate let operation: @Sendable () async -> Void + package func receive() async { + await operation() + } + } + + package func sendPendingRecordZoneChanges( options: CKSyncEngine.SendChangesOptions = CKSyncEngine.SendChangesOptions(), scope: CKDatabase.Scope, forceAtomicByZone: Bool? = nil, @@ -207,7 +214,7 @@ filePath: StaticString = #filePath, line: UInt = #line, column: UInt = #column - ) async throws { + ) async throws -> SendRecordsCallback { let syncEngine = syncEngine(for: scope) guard !syncEngine.state.pendingRecordZoneChanges.isEmpty else { @@ -218,7 +225,7 @@ line: line, column: column ) - return + return SendRecordsCallback {} } guard try await container.accountStatus() == .available else { @@ -231,7 +238,7 @@ line: line, column: column ) - return + return SendRecordsCallback {} } var batch = await nextRecordZoneChangeBatch( @@ -254,7 +261,9 @@ batch?.atomicByZone = forceAtomicByZone } guard let batch - else { return } + else { + return SendRecordsCallback {} + } let (saveResults, deleteResults) = try syncEngine.database.modifyRecords( saving: batch.recordsToSave, @@ -302,16 +311,39 @@ pendingRecordZoneChanges: failedRecordDeletes.keys.map { .deleteRecord($0) } ) - await syncEngine.parentSyncEngine - .handleEvent( - .sentRecordZoneChanges( - savedRecords: savedRecords, - failedRecordSaves: failedRecordSaves, - deletedRecordIDs: deletedRecordIDs, - failedRecordDeletes: failedRecordDeletes - ), - syncEngine: syncEngine - ) + return SendRecordsCallback { [savedRecords, failedRecordSaves, deletedRecordIDs, failedRecordDeletes] in + await syncEngine.parentSyncEngine + .handleEvent( + .sentRecordZoneChanges( + savedRecords: savedRecords, + failedRecordSaves: failedRecordSaves, + deletedRecordIDs: deletedRecordIDs, + failedRecordDeletes: failedRecordDeletes + ), + syncEngine: syncEngine + ) + } + } + + package func processPendingRecordZoneChanges( + options: CKSyncEngine.SendChangesOptions = CKSyncEngine.SendChangesOptions(), + scope: CKDatabase.Scope, + forceAtomicByZone: Bool? = nil, + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + line: UInt = #line, + column: UInt = #column + ) async throws { + try await sendPendingRecordZoneChanges( + options: options, + scope: scope, + forceAtomicByZone: forceAtomicByZone, + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) + .receive() } package func processPendingDatabaseChanges( diff --git a/Sources/SQLiteData/CloudKit/Internal/PendingRecordZoneChange.swift b/Sources/SQLiteData/CloudKit/Internal/PendingRecordZoneChange.swift index fad64e0d..4772ad69 100644 --- a/Sources/SQLiteData/CloudKit/Internal/PendingRecordZoneChange.swift +++ b/Sources/SQLiteData/CloudKit/Internal/PendingRecordZoneChange.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @Table("sqlitedata_icloud_pendingRecordZoneChanges") diff --git a/Sources/SQLiteData/CloudKit/Internal/Pragmas.swift b/Sources/SQLiteData/CloudKit/Internal/Pragmas.swift index e30a254f..798f58c2 100644 --- a/Sources/SQLiteData/CloudKit/Internal/Pragmas.swift +++ b/Sources/SQLiteData/CloudKit/Internal/Pragmas.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) @Table struct PragmaDatabaseList { static var tableAlias: String? { "databases" } diff --git a/Sources/SQLiteData/CloudKit/Internal/RecordType.swift b/Sources/SQLiteData/CloudKit/Internal/RecordType.swift index 4c610b80..ea440f28 100644 --- a/Sources/SQLiteData/CloudKit/Internal/RecordType.swift +++ b/Sources/SQLiteData/CloudKit/Internal/RecordType.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) @Table("sqlitedata_icloud_recordTypes") package struct RecordType: Hashable { @Column(primaryKey: true) diff --git a/Sources/SQLiteData/CloudKit/Internal/SQLiteSchema.swift b/Sources/SQLiteData/CloudKit/Internal/SQLiteSchema.swift index 40fa7d87..2d9b629d 100644 --- a/Sources/SQLiteData/CloudKit/Internal/SQLiteSchema.swift +++ b/Sources/SQLiteData/CloudKit/Internal/SQLiteSchema.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) @Table("sqlite_schema") package struct SQLiteSchema { package let type: ObjectType diff --git a/Sources/SQLiteData/CloudKit/Internal/StateSerialization.swift b/Sources/SQLiteData/CloudKit/Internal/StateSerialization.swift index 2b76b33b..5febee44 100644 --- a/Sources/SQLiteData/CloudKit/Internal/StateSerialization.swift +++ b/Sources/SQLiteData/CloudKit/Internal/StateSerialization.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import StructuredQueriesCore diff --git a/Sources/SQLiteData/CloudKit/Internal/SyncEngine.Event.swift b/Sources/SQLiteData/CloudKit/Internal/SyncEngine.Event.swift index 230aac02..12f42947 100644 --- a/Sources/SQLiteData/CloudKit/Internal/SyncEngine.Event.swift +++ b/Sources/SQLiteData/CloudKit/Internal/SyncEngine.Event.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol+Live.swift b/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol+Live.swift index d462e198..4055aaf6 100644 --- a/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol+Live.swift +++ b/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol+Live.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol.swift b/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol.swift index 58cff003..8857f998 100644 --- a/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol.swift +++ b/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/TableInfo.swift b/Sources/SQLiteData/CloudKit/Internal/TableInfo.swift index 2207ce94..415c4036 100644 --- a/Sources/SQLiteData/CloudKit/Internal/TableInfo.swift +++ b/Sources/SQLiteData/CloudKit/Internal/TableInfo.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import StructuredQueriesCore @Table diff --git a/Sources/SQLiteData/CloudKit/Internal/Triggers.swift b/Sources/SQLiteData/CloudKit/Internal/Triggers.swift index 5085b05a..99a16c52 100644 --- a/Sources/SQLiteData/CloudKit/Internal/Triggers.swift +++ b/Sources/SQLiteData/CloudKit/Internal/Triggers.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import Foundation diff --git a/Sources/SQLiteData/CloudKit/Internal/UnsyncedRecordID.swift b/Sources/SQLiteData/CloudKit/Internal/UnsyncedRecordID.swift index f24a3e04..d138c951 100644 --- a/Sources/SQLiteData/CloudKit/Internal/UnsyncedRecordID.swift +++ b/Sources/SQLiteData/CloudKit/Internal/UnsyncedRecordID.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import StructuredQueriesCore diff --git a/Sources/SQLiteData/CloudKit/Internal/UserDatabase.swift b/Sources/SQLiteData/CloudKit/Internal/UserDatabase.swift index b0fb5edc..1c651213 100644 --- a/Sources/SQLiteData/CloudKit/Internal/UserDatabase.swift +++ b/Sources/SQLiteData/CloudKit/Internal/UserDatabase.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Dependencies package struct UserDatabase { diff --git a/Sources/SQLiteData/CloudKit/Internal/_SendableMetatype.swift b/Sources/SQLiteData/CloudKit/Internal/_SendableMetatype.swift index 55ccae7f..28ea67c0 100644 --- a/Sources/SQLiteData/CloudKit/Internal/_SendableMetatype.swift +++ b/Sources/SQLiteData/CloudKit/Internal/_SendableMetatype.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) #if swift(>=6.2) public typealias _SendableMetatype = SendableMetatype #else diff --git a/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift b/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift index 9a97fb0b..9473c61c 100644 --- a/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift +++ b/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift @@ -1,104 +1,118 @@ -#if canImport(CloudKit) && canImport(CryptoKit) +#if canImport(CloudKit) && canImport(CryptoKit) && !compiler(>=6.3) import CryptoKit import Foundation - @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) - extension SyncEngine { - /// Migrates integer primary-keyed tables and tables without primary keys to - /// CloudKit-compatible, UUID primary keys. - /// - /// To synchronize a table to CloudKit it must have a primary key, and that primary key must - /// be a globally unique identifier, such as a UUID. However, changing the type of a column - /// in SQLite is a [multi-step process] that must be followed very carefully, otherwise you run - /// the risk of corrupting your users' data. - /// - /// [multi-step process]: https://sqlite.org/lang_altertable.html#making_other_kinds_of_table_schema_changes - /// - /// This method is a general purpose tool that analyzes a set of tables to try to automatically - /// perform that migration for you. It performs the following steps: - /// - /// * Computes a random salt to use for backfilling existing integer primary keys with UUIDs. - /// * For each table passed to this method: - /// * Creates a new table with essentially the same schema, but the following changes: - /// * A new temporary name is given to the table. - /// * If an integer primary key exists, it is changed to a "TEXT" column with a - /// "NOT NULL PRIMARY KEY ON CONFLICT REPLACE DEFAULT" constraint, and a default of - /// "uuid()" if no `uuid` argument is given, otherwise the argument is used. - /// * If no primary key exists, one is added with the same constraints as above. - /// * All integer foreign keys are changed to "TEXT" columns with no other changes. - /// * All data from the existing table is copied over into the new table, but all integer - /// IDs (both primary and foreign keys) are transformed into UUIDs by MD5 hashing the - /// integer, the table name, and the salt mentioned above, and turning that hash into a - /// UUID. - /// * The existing table is dropped. - /// * Thew new table is renamed to have the same name as the table just dropped. - /// * Any indexes and stored triggers that were removed from dropping tables in the steps - /// above are recreated. - /// * Executes a "PRAGMA foreign_key_check;" query to make sure that the integrity of the data - /// is preserved. - /// - /// If all of those steps are performed without throwing an error, then your schema and data - /// should have been successfully migrated to UUIDs. If an error is thrown for any reason, - /// then it means the tool was not able to safely migrate your data and so you will need to - /// perform the migration [manually](). - /// - /// - Parameters: - /// - db: A database connection. - /// - tables: Tables to migrate. - /// - uuidFunction: A UUID function to use for the default value of primary keys in your - /// tables' schemas. If `nil`, SQLite's `uuid` function will be used. - public static func migratePrimaryKeys( - _ db: Database, - tables: repeat (each T).Type, - dropUniqueConstraints: Bool = false, - uuid uuidFunction: (any ScalarDatabaseFunction<(), UUID>)? = nil - ) throws - where - repeat (each T).PrimaryKey.QueryOutput: IdentifierStringConvertible, - repeat (each T).TableColumns.PrimaryColumn: TableColumnExpression - { - let salt = - (try uuidFunction.flatMap { uuid -> UUID? in - try #sql("SELECT \(quote: uuid.name)()", as: UUID.self).fetchOne(db) - } - ?? UUID()).uuidString + // NB: Swift 6.2.3 and 6.3-dev crash when compiling the primary key migration feature + // due to a compiler bug with #sql macro interpolation combined with $backfillUUID + // (macro-generated database function). + // + // This entire feature is disabled on Swift 6.2.3+ until the compiler bug is fixed. + // See detailed comments below in the PrimaryKeyedTable extension. + // + // Tracking: https://github.com/doozMen/sqlite-data/issues/2 + // TODO: Re-enable when Swift 6.3 stabilizes or compiler bug is fixed. + #if !compiler(>=6.2.3) + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + extension SyncEngine { + /// Migrates integer primary-keyed tables and tables without primary keys to + /// CloudKit-compatible, UUID primary keys. + /// + /// To synchronize a table to CloudKit it must have a primary key, and that primary key must + /// be a globally unique identifier, such as a UUID. However, changing the type of a column + /// in SQLite is a [multi-step process] that must be followed very carefully, otherwise you run + /// the risk of corrupting your users' data. + /// + /// [multi-step process]: https://sqlite.org/lang_altertable.html#making_other_kinds_of_table_schema_changes + /// + /// This method is a general purpose tool that analyzes a set of tables to try to automatically + /// perform that migration for you. It performs the following steps: + /// + /// * Computes a random salt to use for backfilling existing integer primary keys with UUIDs. + /// * For each table passed to this method: + /// * Creates a new table with essentially the same schema, but the following changes: + /// * A new temporary name is given to the table. + /// * If an integer primary key exists, it is changed to a "TEXT" column with a + /// "NOT NULL PRIMARY KEY ON CONFLICT REPLACE DEFAULT" constraint, and a default of + /// "uuid()" if no `uuid` argument is given, otherwise the argument is used. + /// * If no primary key exists, one is added with the same constraints as above. + /// * All integer foreign keys are changed to "TEXT" columns with no other changes. + /// * All data from the existing table is copied over into the new table, but all integer + /// IDs (both primary and foreign keys) are transformed into UUIDs by MD5 hashing the + /// integer, the table name, and the salt mentioned above, and turning that hash into a + /// UUID. + /// * The existing table is dropped. + /// * Thew new table is renamed to have the same name as the table just dropped. + /// * Any indexes and stored triggers that were removed from dropping tables in the steps + /// above are recreated. + /// * Executes a "PRAGMA foreign_key_check;" query to make sure that the integrity of the data + /// is preserved. + /// + /// If all of those steps are performed without throwing an error, then your schema and data + /// should have been successfully migrated to UUIDs. If an error is thrown for any reason, + /// then it means the tool was not able to safely migrate your data and so you will need to + /// perform the migration [manually](). + /// + /// - Note: This method is unavailable on Swift 6.2.3+ due to a compiler bug. + /// See https://github.com/doozMen/sqlite-data/issues/2 + /// + /// - Parameters: + /// - db: A database connection. + /// - tables: Tables to migrate. + /// - uuidFunction: A UUID function to use for the default value of primary keys in your + /// tables' schemas. If `nil`, SQLite's `uuid` function will be used. + public static func migratePrimaryKeys( + _ db: Database, + tables: repeat (each T).Type, + dropUniqueConstraints: Bool = false, + uuid uuidFunction: (any ScalarDatabaseFunction<(), UUID>)? = nil + ) throws + where + repeat (each T).PrimaryKey.QueryOutput: IdentifierStringConvertible, + repeat (each T).TableColumns.PrimaryColumn: TableColumnExpression + { + let salt = + (try uuidFunction.flatMap { uuid -> UUID? in + try #sql("SELECT \(quote: uuid.name)()", as: UUID.self).fetchOne(db) + } + ?? UUID()).uuidString - db.add(function: $backfillUUID) - defer { db.remove(function: $backfillUUID) } + db.add(function: $backfillUUID) + defer { db.remove(function: $backfillUUID) } - var migratedTableNames: [String] = [] - for table in repeat each tables { - migratedTableNames.append(table.tableName) - } - let indicesAndTriggersSQL = - try SQLiteSchema - .select(\.sql) - .where { - $0.tableName.in(migratedTableNames) - && $0.type.in([#bind(.index), #bind(.trigger)]) - && $0.sql.isNot(nil) + var migratedTableNames: [String] = [] + for table in repeat each tables { + migratedTableNames.append(table.tableName) + } + let indicesAndTriggersSQL = + try SQLiteSchema + .select(\.sql) + .where { + $0.tableName.in(migratedTableNames) + && $0.type.in([#bind(.index), #bind(.trigger)]) + && $0.sql.isNot(nil) + } + .fetchAll(db) + .compactMap(\.self) + for table in repeat each tables { + try table.migratePrimaryKeyToUUID( + db: db, + dropUniqueConstraints: dropUniqueConstraints, + uuidFunction: uuidFunction, + migratedTableNames: migratedTableNames, + salt: salt + ) + } + for sql in indicesAndTriggersSQL { + try #sql(QueryFragment(stringLiteral: sql)).execute(db) } - .fetchAll(db) - .compactMap(\.self) - for table in repeat each tables { - try table.migratePrimaryKeyToUUID( - db: db, - dropUniqueConstraints: dropUniqueConstraints, - uuidFunction: uuidFunction, - migratedTableNames: migratedTableNames, - salt: salt - ) - } - for sql in indicesAndTriggersSQL { - try #sql(QueryFragment(stringLiteral: sql)).execute(db) - } - let foreignKeyChecks = try PragmaForeignKeyCheck.all.fetchAll(db) - if !foreignKeyChecks.isEmpty { - throw ForeignKeyCheckError(checks: foreignKeyChecks) + let foreignKeyChecks = try PragmaForeignKeyCheck.all.fetchAll(db) + if !foreignKeyChecks.isEmpty { + throw ForeignKeyCheckError(checks: foreignKeyChecks) + } } } - } + #endif private struct MigrationError: LocalizedError { let reason: Reason @@ -124,108 +138,127 @@ } } - @available(iOS 16, macOS 13, tvOS 13, watchOS 9, *) - extension PrimaryKeyedTable where TableColumns.PrimaryColumn: TableColumnExpression { - fileprivate static func migratePrimaryKeyToUUID( - db: Database, - dropUniqueConstraints: Bool, - uuidFunction: (any ScalarDatabaseFunction<(), UUID>)? = nil, - migratedTableNames: [String], - salt: String - ) throws { - let schema = - try SQLiteSchema - .select(\.sql) - .where { $0.type.eq(#bind(.table)) && $0.tableName.eq(tableName) } - .fetchOne(db) - ?? nil - - guard let schema - else { - throw MigrationError(reason: .tableNotFound(tableName)) - } + // NB: Swift 6.2.3 and 6.3-dev crash when compiling this extension due to a compiler bug + // with #sql macro interpolation combined with $backfillUUID (macro-generated database + // function) in complex control flow. + // + // Error: "Assertion failed: (Start.isValid() == End.isValid() && 'Start and end should + // either both be valid or both be invalid!'), function SourceRange, file SourceLoc.h" + // + // This is a CloudKit-specific migration feature that: + // 1. Is only relevant on Apple platforms (CloudKit doesn't exist on Linux/Android) + // 2. Is used for migrating existing integer primary keys to UUID primary keys + // 3. Is not needed for new databases or cross-platform builds + // + // Workaround: Disable on Swift 6.2.3+ until the compiler bug is fixed. + // Tracking: https://github.com/doozMen/sqlite-data/issues/2 + // TODO: Re-enable when Swift 6.3 stabilizes or compiler bug is fixed. + #if !compiler(>=6.2.3) + @available(iOS 16, macOS 13, tvOS 13, watchOS 9, *) + extension PrimaryKeyedTable where TableColumns.PrimaryColumn: TableColumnExpression { + fileprivate static func migratePrimaryKeyToUUID( + db: Database, + dropUniqueConstraints: Bool, + uuidFunction: (any ScalarDatabaseFunction<(), UUID>)? = nil, + migratedTableNames: [String], + salt: String + ) throws { + let schema = + try SQLiteSchema + .select(\.sql) + .where { $0.type.eq(#bind(.table)) && $0.tableName.eq(tableName) } + .fetchOne(db) + ?? nil + + guard let schema + else { + throw MigrationError(reason: .tableNotFound(tableName)) + } - let tableInfo = try PragmaTableInfo.all.fetchAll(db) - let primaryKeys = tableInfo.filter(\.isPrimaryKey) - guard - (primaryKeys.count == 1 && primaryKeys[0].isInt) - || primaryKeys.isEmpty - else { - throw MigrationError(reason: .invalidPrimaryKey) - } - guard primaryKeys.count <= 1 - else { - throw MigrationError(reason: .invalidPrimaryKey) - } + let tableInfo = try PragmaTableInfo.all.fetchAll(db) + let primaryKeys = tableInfo.filter(\.isPrimaryKey) + guard + (primaryKeys.count == 1 && primaryKeys[0].isInt) + || primaryKeys.isEmpty + else { + throw MigrationError(reason: .invalidPrimaryKey) + } + guard primaryKeys.count <= 1 + else { + throw MigrationError(reason: .invalidPrimaryKey) + } - let foreignKeys = try PragmaForeignKeyList.all.fetchAll(db) - guard foreignKeys.allSatisfy({ migratedTableNames.contains($0.table) }) - else { - throw MigrationError(reason: .invalidForeignKey) - } + let foreignKeys = try PragmaForeignKeyList.all.fetchAll(db) + guard foreignKeys.allSatisfy({ migratedTableNames.contains($0.table) }) + else { + throw MigrationError(reason: .invalidForeignKey) + } - let newTableName = "new_\(tableName)" - let uuidFunction = uuidFunction?.name ?? "uuid" - let newSchema = try schema.rewriteSchema( - dropUniqueConstraints: dropUniqueConstraints, - oldPrimaryKey: primaryKeys.first?.name, - newPrimaryKey: columns.primaryKey.name, - foreignKeys: foreignKeys.map(\.from), - uuidFunction: uuidFunction - ) + let newTableName = "new_\(tableName)" + let uuidFunction = uuidFunction?.name ?? "uuid" + let newSchema = try schema.rewriteSchema( + dropUniqueConstraints: dropUniqueConstraints, + oldPrimaryKey: primaryKeys.first?.name, + newPrimaryKey: columns.primaryKey.name, + foreignKeys: foreignKeys.map(\.from), + uuidFunction: uuidFunction + ) - var newColumns: [String] = [] - var convertedColumns: [QueryFragment] = [] - if primaryKeys.first == nil { - convertedColumns.append("NULL") - newColumns.append(columns.primaryKey.name) - } - newColumns.append(contentsOf: tableInfo.map(\.name)) - convertedColumns.append( - contentsOf: tableInfo.map { tableInfo -> QueryFragment in - if tableInfo.name == primaryKey.name, tableInfo.isInt { - return $backfillUUID(id: #sql("\(quote: tableInfo.name)"), table: tableName, salt: salt) + var newColumns: [String] = [] + var convertedColumns: [QueryFragment] = [] + if primaryKeys.first == nil { + convertedColumns.append("NULL") + newColumns.append(columns.primaryKey.name) + } + newColumns.append(contentsOf: tableInfo.map(\.name)) + convertedColumns.append( + contentsOf: tableInfo.map { tableInfo -> QueryFragment in + if tableInfo.name == primaryKey.name, tableInfo.isInt { + return $backfillUUID( + id: #sql("\(quote: tableInfo.name)"), table: tableName, salt: salt + ) .queryFragment - } else if tableInfo.isInt, - let foreignKey = foreignKeys.first(where: { $0.from == tableInfo.name }) - { - return $backfillUUID( - id: #sql("\(quote: foreignKey.from)"), - table: foreignKey.table, - salt: salt - ) - .queryFragment - } else { - return QueryFragment(quote: tableInfo.name) + } else if tableInfo.isInt, + let foreignKey = foreignKeys.first(where: { $0.from == tableInfo.name }) + { + return $backfillUUID( + id: #sql("\(quote: foreignKey.from)"), + table: foreignKey.table, + salt: salt + ) + .queryFragment + } else { + return QueryFragment(quote: tableInfo.name) + } } - } - ) + ) - try #sql(QueryFragment(stringLiteral: newSchema)).execute(db) - try #sql( - """ - INSERT INTO \(quote: newTableName) \ - ("rowid", \(newColumns.map { "\(quote: $0)" }.joined(separator: ", "))) - SELECT "rowid", \(convertedColumns.joined(separator: ", ")) \ - FROM \(Self.self) - ORDER BY "rowid" - """ - ) - .execute(db) - try #sql( - """ - DROP TABLE \(Self.self) - """ - ) - .execute(db) - try #sql( - """ - ALTER TABLE \(quote: newTableName) RENAME TO \(Self.self) - """ - ) - .execute(db) + try #sql(QueryFragment(stringLiteral: newSchema)).execute(db) + try #sql( + """ + INSERT INTO \(quote: newTableName) \ + ("rowid", \(newColumns.map { "\(quote: $0)" }.joined(separator: ", "))) + SELECT "rowid", \(convertedColumns.joined(separator: ", ")) \ + FROM \(Self.self) + ORDER BY "rowid" + """ + ) + .execute(db) + try #sql( + """ + DROP TABLE \(Self.self) + """ + ) + .execute(db) + try #sql( + """ + ALTER TABLE \(quote: newTableName) RENAME TO \(Self.self) + """ + ) + .execute(db) + } } - } + #endif extension StringProtocol { fileprivate func quoted() -> String { diff --git a/Sources/SQLiteData/CloudKit/SyncEngine.swift b/Sources/SQLiteData/CloudKit/SyncEngine.swift index 878e832f..ca9995bb 100644 --- a/Sources/SQLiteData/CloudKit/SyncEngine.swift +++ b/Sources/SQLiteData/CloudKit/SyncEngine.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import ConcurrencyExtras import Dependencies @@ -38,7 +38,7 @@ private let notificationsObserver = LockIsolated<(any NSObjectProtocol)?>(nil) private let activityCounts = LockIsolated(ActivityCounts()) private let startTask = LockIsolated?>(nil) - #if canImport(DeveloperToolsSupport) + #if DEBUG && canImport(DeveloperToolsSupport) private let previewTimerTask = LockIsolated?>(nil) #endif @@ -91,7 +91,7 @@ privateTables: repeat (each T2).Type, containerIdentifier: String? = nil, defaultZone: CKRecordZone = CKRecordZone(zoneName: "co.pointfree.SQLiteData.defaultZone"), - startImmediately: Bool = true, + startImmediately: Bool? = nil, delegate: (any SyncEngineDelegate)? = nil, logger: Logger = isTesting ? Logger(.disabled) : Logger(subsystem: "SQLiteData", category: "CloudKit") @@ -106,7 +106,7 @@ let containerIdentifier = containerIdentifier ?? ModelConfiguration(groupContainer: .automatic).cloudKitContainerIdentifier - ?? (context == .preview ? "preview" : nil) + ?? (context != .live ? "container" : nil) var allTables: [any SynchronizableTable] = [] var allPrivateTables: [any SynchronizableTable] = [] for table in repeat each tables { @@ -152,7 +152,7 @@ privateTables: allPrivateTables ) try setUpSyncEngine() - if startImmediately { + if startImmediately ?? !isTesting { _ = try start() } return @@ -173,7 +173,7 @@ database: container.privateCloudDatabase, stateSerialization: try? metadatabase.read { db in try StateSerialization - .find(#bind(.private)) + .where { $0.scope == #bind(.private) } .select(\.data) .fetchOne(db) }, @@ -185,7 +185,7 @@ database: container.sharedCloudDatabase, stateSerialization: try? metadatabase.read { db in try StateSerialization - .find(#bind(.shared)) + .where { $0.scope == #bind(.shared) } .select(\.data) .fetchOne(db) }, @@ -201,7 +201,7 @@ privateTables: allPrivateTables ) try setUpSyncEngine() - if startImmediately { + if startImmediately ?? !isTesting { _ = try start() } } @@ -423,7 +423,7 @@ /// You must start the sync engine again using ``start()`` to synchronize the changes. public func stop() { guard isRunning else { return } - #if canImport(DeveloperToolsSupport) + #if DEBUG && canImport(DeveloperToolsSupport) previewTimerTask.withValue { $0?.cancel() $0 = nil @@ -503,7 +503,7 @@ } ) - #if canImport(DeveloperToolsSupport) + #if DEBUG && canImport(DeveloperToolsSupport) @Dependency(\.context) var context @Dependency(\.continuousClock) var clock if context == .preview { @@ -899,7 +899,15 @@ /// See for more info. @DatabaseFunction("sqlitedata_icloud_syncEngineIsSynchronizingChanges") public static var isSynchronizing: Bool { - _isSynchronizingChanges + if _isCreatingTemporaryTrigger { + reportIssue( + """ + Invoked 'SyncEngine.isSynchronizing' at trigger creation, which is unexpected. Use \ + 'SyncEngine.$isSynchronizing' to invoke at trigger execution, instead. + """ + ) + } + return _isSynchronizingChanges } @available(*, deprecated, message: "Use 'SyncEngine.$isSynchronizing', instead.") @@ -1167,14 +1175,17 @@ } func open(_: some SynchronizableTable) async -> CKRecord? { let row = - withErrorReporting(.sqliteDataCloudKitFailure) { - try userDatabase.read { db in - try T + await withErrorReporting(.sqliteDataCloudKitFailure) { + // NB: Fake 'sending' result. + nonisolated(unsafe) var result: T.QueryOutput? + try await userDatabase.read { db in + result = try T .where { #sql("\($0.primaryKey) = \(bind: metadata.recordPrimaryKey)") } .fetchOne(db) } + return result } ?? nil guard let row @@ -1892,8 +1903,12 @@ db: Database ) { withErrorReporting(.sqliteDataCloudKitFailure) { - guard let recordPrimaryKey = serverRecord.recordID.recordPrimaryKey - else { return } + guard + let recordPrimaryKey = serverRecord.recordID.recordPrimaryKey, + serverRecord.encryptedValues[CKRecord.userModificationTimeKey] != nil + else { + return + } try SyncMetadata.insert { SyncMetadata( @@ -2003,7 +2018,9 @@ ) async throws -> QueryFragment { let nonPrimaryKeyChangedColumns = changedColumnNames - .filter { $0 != T.primaryKey.name } + .filter { + $0 != T.primaryKey.name && record.hasSet(key: $0) + } guard !nonPrimaryKeyChangedColumns.isEmpty else { @@ -2195,7 +2212,7 @@ let containerIdentifier = containerIdentifier ?? ModelConfiguration(groupContainer: .automatic).cloudKitContainerIdentifier - ?? (context == .preview ? "preview" : nil) + ?? (context != .live ? "container" : nil) guard let containerIdentifier else { throw SyncEngine.SchemaError.noCloudKitContainer @@ -2224,7 +2241,7 @@ url.isInMemory ? try DatabaseQueue(path: path) : try DatabasePool(path: path) - _ = try database.write { db in + _ = try database.read { db in try #sql("SELECT 1").execute(db) } try #sql( @@ -2424,7 +2441,9 @@ self.lastKnownServerRecord = lastKnownServerRecord self._lastKnownServerRecordAllFields = lastKnownServerRecord if let lastKnownServerRecord { - self.userModificationTime = lastKnownServerRecord.userModificationTime + self.userModificationTime = #sql(""" + max(\(self.userModificationTime), \(lastKnownServerRecord.userModificationTime)) + """) } } } @@ -2435,13 +2454,19 @@ record: CKRecord, columnNames: some Collection ) -> QueryFragment { - let allColumnNames = T.TableColumns.writableColumns.map(\.name) + let setColumnNames = T.TableColumns.writableColumns.map(\.name) + .filter { record.hasSet(key: $0) } + guard !setColumnNames.isEmpty + else { + return "" + } + let columnNames = columnNames.filter { setColumnNames.contains($0) } let hasNonPrimaryKeyColumns = columnNames.contains { $0 != T.primaryKey.name } var query: QueryFragment = "INSERT INTO \(T.self) (" - query.append(allColumnNames.map { "\(quote: $0)" }.joined(separator: ", ")) + query.append(setColumnNames.map { "\(quote: $0)" }.joined(separator: ", ")) query.append(") VALUES (") query.append( - allColumnNames + setColumnNames .map { columnName in if let asset = record[columnName] as? CKAsset { @Dependency(\.dataManager) var dataManager diff --git a/Sources/SQLiteData/CloudKit/SyncEngineDelegate.swift b/Sources/SQLiteData/CloudKit/SyncEngineDelegate.swift index b373dfc4..60c16adb 100644 --- a/Sources/SQLiteData/CloudKit/SyncEngineDelegate.swift +++ b/Sources/SQLiteData/CloudKit/SyncEngineDelegate.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import CustomDump diff --git a/Sources/SQLiteData/CloudKit/SyncMetadata.swift b/Sources/SQLiteData/CloudKit/SyncMetadata.swift index 22990098..67fcd71b 100644 --- a/Sources/SQLiteData/CloudKit/SyncMetadata.swift +++ b/Sources/SQLiteData/CloudKit/SyncMetadata.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit /// A table that tracks metadata related to synchronized data. diff --git a/Sources/SQLiteData/FetchOne.swift b/Sources/SQLiteData/FetchOne.swift index e9e4312e..9eb47a1f 100644 --- a/Sources/SQLiteData/FetchOne.swift +++ b/Sources/SQLiteData/FetchOne.swift @@ -121,7 +121,7 @@ public struct FetchOne: Sendable { database: (any DatabaseReader)? = nil ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value: StructuredQueriesCore.Table, Value.QueryOutput == Value { @@ -230,7 +230,7 @@ public struct FetchOne: Sendable { database: (any DatabaseReader)? = nil ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value == S.From.QueryOutput?, S.QueryValue == (), S.Joins == () @@ -255,9 +255,9 @@ public struct FetchOne: Sendable { database: (any DatabaseReader)? = nil ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, S.QueryValue: QueryRepresentable, - S.QueryValue: _OptionalProtocol, + S.QueryValue: StructuredQueriesCore._OptionalProtocol, Value == S.QueryValue.QueryOutput { sharedReader = SharedReader( @@ -283,7 +283,7 @@ public struct FetchOne: Sendable { ) where Value: QueryRepresentable, - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value.QueryOutput == Value { sharedReader = SharedReader( @@ -368,7 +368,7 @@ public struct FetchOne: Sendable { database: (any DatabaseReader)? = nil ) async throws -> FetchSubscription where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value == S.From.QueryOutput?, S.QueryValue == (), S.Joins == () @@ -393,9 +393,9 @@ public struct FetchOne: Sendable { database: (any DatabaseReader)? = nil ) async throws -> FetchSubscription where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, S.QueryValue: QueryRepresentable, - S.QueryValue: _OptionalProtocol, + S.QueryValue: StructuredQueriesCore._OptionalProtocol, Value == S.QueryValue.QueryOutput { try await sharedReader.load( @@ -418,7 +418,7 @@ public struct FetchOne: Sendable { ) async throws -> FetchSubscription where Value: QueryRepresentable, - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value.QueryOutput == Value { try await sharedReader.load( @@ -449,7 +449,7 @@ extension FetchOne { scheduler: some ValueObservationScheduler & Hashable ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value: _Selection, Value.QueryOutput == Value { @@ -497,7 +497,7 @@ extension FetchOne { scheduler: some ValueObservationScheduler & Hashable ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value: StructuredQueriesCore.Table, Value.QueryOutput == Value { @@ -637,7 +637,7 @@ extension FetchOne { scheduler: some ValueObservationScheduler & Hashable ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value == S.From.QueryOutput?, S.QueryValue == (), S.Joins == () @@ -669,9 +669,9 @@ extension FetchOne { scheduler: some ValueObservationScheduler & Hashable ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, S.QueryValue: QueryRepresentable, - S.QueryValue: _OptionalProtocol, + S.QueryValue: StructuredQueriesCore._OptionalProtocol, Value == S.QueryValue.QueryOutput { sharedReader = SharedReader( @@ -701,7 +701,7 @@ extension FetchOne { ) where Value: QueryRepresentable, - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value.QueryOutput == Value { sharedReader = SharedReader( @@ -810,7 +810,7 @@ extension FetchOne { scheduler: some ValueObservationScheduler & Hashable ) async throws -> FetchSubscription where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value == S.From.QueryOutput?, S.QueryValue == (), S.Joins == () @@ -842,9 +842,9 @@ extension FetchOne { scheduler: some ValueObservationScheduler & Hashable ) async throws -> FetchSubscription where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, S.QueryValue: QueryRepresentable, - S.QueryValue: _OptionalProtocol, + S.QueryValue: StructuredQueriesCore._OptionalProtocol, Value == S.QueryValue.QueryOutput { try await sharedReader.load( @@ -874,7 +874,7 @@ extension FetchOne { ) async throws -> FetchSubscription where Value: QueryRepresentable, - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value.QueryOutput == Value { try await sharedReader.load( @@ -926,7 +926,7 @@ extension FetchOne: Equatable where Value: Equatable { animation: Animation ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value: _Selection, Value.QueryOutput == Value { @@ -968,7 +968,7 @@ extension FetchOne: Equatable where Value: Equatable { animation: Animation ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value: StructuredQueriesCore.Table, Value.QueryOutput == Value { @@ -1103,7 +1103,7 @@ extension FetchOne: Equatable where Value: Equatable { animation: Animation ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value == S.From.QueryOutput?, S.QueryValue == (), S.Joins == () @@ -1133,9 +1133,9 @@ extension FetchOne: Equatable where Value: Equatable { animation: Animation ) where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, S.QueryValue: QueryRepresentable, - S.QueryValue: _OptionalProtocol, + S.QueryValue: StructuredQueriesCore._OptionalProtocol, Value == S.QueryValue.QueryOutput { self.init( @@ -1164,7 +1164,7 @@ extension FetchOne: Equatable where Value: Equatable { ) where Value: QueryRepresentable, - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value.QueryOutput == Value { self.init( @@ -1260,7 +1260,7 @@ extension FetchOne: Equatable where Value: Equatable { animation: Animation ) async throws -> FetchSubscription where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value == S.From.QueryOutput?, S.QueryValue == (), S.Joins == () @@ -1285,9 +1285,9 @@ extension FetchOne: Equatable where Value: Equatable { animation: Animation ) async throws -> FetchSubscription where - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, S.QueryValue: QueryRepresentable, - S.QueryValue: _OptionalProtocol, + S.QueryValue: StructuredQueriesCore._OptionalProtocol, Value == S.QueryValue.QueryOutput { try await load(statement, database: database, scheduler: .animation(animation)) @@ -1311,7 +1311,7 @@ extension FetchOne: Equatable where Value: Equatable { ) async throws -> FetchSubscription where Value: QueryRepresentable, - Value: _OptionalProtocol, + Value: StructuredQueriesCore._OptionalProtocol, Value.QueryOutput == Value { try await load(statement, database: database, scheduler: .animation(animation)) @@ -1344,8 +1344,8 @@ private struct FetchOneStatementOptionalValueRequest: } private struct FetchOneStatementOptionalProtocolRequest< - Value: QueryRepresentable & _OptionalProtocol ->: StatementKeyRequest where Value.QueryOutput: _OptionalProtocol { + Value: QueryRepresentable & StructuredQueriesCore._OptionalProtocol +>: StatementKeyRequest where Value.QueryOutput: StructuredQueriesCore._OptionalProtocol { let statement: SQLQueryExpression init(statement: some StructuredQueriesCore.Statement) { self.statement = SQLQueryExpression(statement) diff --git a/Sources/SQLiteData/FetchSubscription.swift b/Sources/SQLiteData/FetchSubscription.swift index 10565f14..9ce8f893 100644 --- a/Sources/SQLiteData/FetchSubscription.swift +++ b/Sources/SQLiteData/FetchSubscription.swift @@ -1,4 +1,4 @@ -import Perception +import ConcurrencyExtras import Sharing /// A subscription associated with `@FetchAll`, `@FetchOne`, and `@Fetch` observation. diff --git a/Sources/SQLiteData/Internal/ISO8601.swift b/Sources/SQLiteData/Internal/ISO8601.swift index 451d16c0..1e9ce773 100644 --- a/Sources/SQLiteData/Internal/ISO8601.swift +++ b/Sources/SQLiteData/Internal/ISO8601.swift @@ -3,10 +3,16 @@ import Foundation extension Date { @usableFromInline var iso8601String: String { + let nextUpDate = Date(timeIntervalSinceReferenceDate: timeIntervalSinceReferenceDate.nextUp) if #available(iOS 15, macOS 12, tvOS 15, watchOS 8, *) { - return formatted(.iso8601.currentTimestamp(includingFractionalSeconds: true)) + return + nextUpDate + .formatted( + .iso8601.currentTimestamp(includingFractionalSeconds: true) + ) } else { - return DateFormatter.iso8601(includingFractionalSeconds: true).string(from: self) + return DateFormatter.iso8601(includingFractionalSeconds: true) + .string(from: nextUpDate) } } diff --git a/Sources/SQLiteData/StructuredQueries+GRDB/Table+GRDB.swift b/Sources/SQLiteData/StructuredQueries+GRDB/Table+GRDB.swift index 8e55d707..bcf620bc 100644 --- a/Sources/SQLiteData/StructuredQueries+GRDB/Table+GRDB.swift +++ b/Sources/SQLiteData/StructuredQueries+GRDB/Table+GRDB.swift @@ -38,6 +38,8 @@ extension StructuredQueriesCore.Table { } } +// TODO: See if upstream works now +/* extension StructuredQueriesCore.PrimaryKeyedTable { /// Returns a single value fetched from the database for a given primary key. /// @@ -53,3 +55,28 @@ extension StructuredQueriesCore.PrimaryKeyedTable { try all.find(db, key: primaryKey) } } +*/ + +// NB: Swift 6.2.3 and 6.3-dev guard Select.find(_:) in swift-structured-queries due to compiler crashes. +// This extension depends on that method, so it must also be guarded. +// Tracking: https://github.com/doozMen/sqlite-data/issues/2 +#if !compiler(>=6.2.3) + extension StructuredQueriesCore.PrimaryKeyedTable { + /// Returns a single value fetched from the database for a given primary key. + /// + /// - Parameters + /// - db: A database connection. + /// - primaryKey: A primary key identifying a table row. + /// - Returns: A single value decoded from the database. + @inlinable + public static func find( + _ db: Database, + key primaryKey: some QueryExpression + ) throws -> QueryOutput { + guard let record = try Self.all.find(primaryKey).fetchOne(db) else { + throw NotFound() + } + return record + } + } +#endif diff --git a/Tests/SQLiteDataTests/AssertQueryTests.swift b/Tests/SQLiteDataTests/AssertQueryTests.swift index ac82ec53..6e91621a 100644 --- a/Tests/SQLiteDataTests/AssertQueryTests.swift +++ b/Tests/SQLiteDataTests/AssertQueryTests.swift @@ -136,7 +136,7 @@ struct AssertQueryTests { """ SELECT "records"."id", "records"."date" FROM "records" - WHERE ("records"."id") = (1) + WHERE (("records"."id") = (1)) """ } results: { """ diff --git a/Tests/SQLiteDataTests/CloudKitTests/AssetsTests.swift b/Tests/SQLiteDataTests/CloudKitTests/AssetsTests.swift index 7744f34b..95d1204d 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/AssetsTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/AssetsTests.swift @@ -37,7 +37,7 @@ coverImage_hash: Data(32 bytes), remindersListID: 1, coverImage: CKAsset( - fileURL: URL(file:///6105d6cc76af400325e94d588ce511be5bfdbb73b437dc51eca43917d7a43e3d), + fileURL: URL(file:///tmp/6105d6cc76af400325e94d588ce511be5bfdbb73b437dc51eca43917d7a43e3d), dataString: "image" ) ), @@ -61,7 +61,7 @@ inMemoryDataManager.storage.withValue { storage in let url = URL( - string: "file:///6105d6cc76af400325e94d588ce511be5bfdbb73b437dc51eca43917d7a43e3d" + string: "file:///tmp/6105d6cc76af400325e94d588ce511be5bfdbb73b437dc51eca43917d7a43e3d" )! #expect(storage[url] == Data("image".utf8)) } @@ -93,7 +93,7 @@ coverImage_hash: Data(32 bytes), remindersListID: 1, coverImage: CKAsset( - fileURL: URL(file:///97e67a5645969953f1a4cfe2ea75649864ff99789189cdd3f6db03e59f8a8ebf), + fileURL: URL(file:///tmp/97e67a5645969953f1a4cfe2ea75649864ff99789189cdd3f6db03e59f8a8ebf), dataString: "new-image" ) ), @@ -117,7 +117,7 @@ inMemoryDataManager.storage.withValue { storage in let url = URL( - string: "file:///97e67a5645969953f1a4cfe2ea75649864ff99789189cdd3f6db03e59f8a8ebf" + string: "file:///tmp/97e67a5645969953f1a4cfe2ea75649864ff99789189cdd3f6db03e59f8a8ebf" )! #expect(storage[url] == Data("new-image".utf8)) } diff --git a/Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift b/Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift index 5c0a9347..d7332fc9 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift @@ -24,7 +24,7 @@ tableName: "remindersLists", schema: """ CREATE TABLE "remindersLists" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "title" TEXT NOT NULL ON CONFLICT REPLACE DEFAULT '' ) STRICT """, @@ -34,7 +34,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: "\'\'", @@ -101,7 +101,7 @@ tableName: "reminders", schema: """ CREATE TABLE "reminders" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "dueDate" TEXT, "isCompleted" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "priority" INTEGER, @@ -124,7 +124,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [2]: TableInfo( defaultValue: "0", @@ -177,7 +177,7 @@ tableName: "reminderTags", schema: """ CREATE TABLE "reminderTags" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "reminderID" INTEGER NOT NULL REFERENCES "reminders"("id") ON DELETE CASCADE, "tagID" TEXT NOT NULL REFERENCES "tags"("title") ON DELETE CASCADE ON UPDATE CASCADE ) STRICT @@ -188,7 +188,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: nil, @@ -210,7 +210,7 @@ tableName: "parents", schema: """ CREATE TABLE "parents"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + "id" INT PRIMARY KEY NOT NULL ) STRICT """, tableInfo: [ @@ -219,7 +219,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ) ] ), @@ -227,7 +227,7 @@ tableName: "childWithOnDeleteSetNulls", schema: """ CREATE TABLE "childWithOnDeleteSetNulls"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "parentID" INTEGER REFERENCES "parents"("id") ON DELETE SET NULL ON UPDATE SET NULL ) STRICT """, @@ -237,7 +237,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: nil, @@ -252,7 +252,7 @@ tableName: "childWithOnDeleteSetDefaults", schema: """ CREATE TABLE "childWithOnDeleteSetDefaults"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "parentID" INTEGER NOT NULL DEFAULT 0 REFERENCES "parents"("id") ON DELETE SET DEFAULT ON UPDATE SET DEFAULT ) STRICT @@ -263,7 +263,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: "0", @@ -278,7 +278,7 @@ tableName: "modelAs", schema: """ CREATE TABLE "modelAs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "count" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "isEven" INTEGER GENERATED ALWAYS AS ("count" % 2 == 0) VIRTUAL ) @@ -296,7 +296,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ) ] ), @@ -304,7 +304,7 @@ tableName: "modelBs", schema: """ CREATE TABLE "modelBs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "isOn" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "modelAID" INTEGER NOT NULL REFERENCES "modelAs"("id") ON DELETE CASCADE ) @@ -315,7 +315,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: "0", @@ -337,7 +337,7 @@ tableName: "modelCs", schema: """ CREATE TABLE "modelCs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "title" TEXT NOT NULL ON CONFLICT REPLACE DEFAULT '', "modelBID" INTEGER NOT NULL REFERENCES "modelBs"("id") ON DELETE CASCADE ) @@ -348,7 +348,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: nil, @@ -860,7 +860,7 @@ } let record = try syncEngine.private.database.record(for: ModelA.recordID(for: 1)) - record.encryptedValues["isEven"] = false + record.setValue(false, forKey: "isEven", at: 0) try await syncEngine.modifyRecords(scope: .private, saving: [record]).notify() assertInlineSnapshot(of: container, as: .customDump) { diff --git a/Tests/SQLiteDataTests/CloudKitTests/FetchRecordZoneChangesTests.swift b/Tests/SQLiteDataTests/CloudKitTests/FetchRecordZoneChangesTests.swift index 207728c7..60242f49 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/FetchRecordZoneChangesTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/FetchRecordZoneChangesTests.swift @@ -404,8 +404,8 @@ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) @Test func receiveRecord_SingleFieldPrimaryKey() async throws { - let tagRecord = CKRecord(recordType: "tags", recordID: Tag.recordID(for: "weekend")) - tagRecord.encryptedValues["title"] = "weekend" + let tagRecord = CKRecord(recordType: Tag.tableName, recordID: Tag.recordID(for: "weekend")) + tagRecord.setValue("weekend", forKey: "title", at: 0) try await syncEngine.modifyRecords(scope: .private, saving: [tagRecord]).notify() try await userDatabase.read { db in @@ -508,7 +508,7 @@ recordType: Tag.tableName, recordID: Tag.recordID(for: "tag") ) - tagRecord.encryptedValues["title"] = "tag" + tagRecord.setValue("tag", forKey: "title", at: 0) try await syncEngine.modifyRecords(scope: .private, saving: [tagRecord]).notify() assertQuery(Tag.all, database: userDatabase.database) { @@ -583,7 +583,7 @@ recordType: Tag.tableName, recordID: Tag.recordID(for: "tag") ) - tagRecord.encryptedValues["title"] = "tag" + tagRecord.setValue("tag", forKey: "title", at: 0) let modifications = try syncEngine.modifyRecords(scope: .private, saving: [tagRecord]) try await userDatabase.userWrite { db in diff --git a/Tests/SQLiteDataTests/CloudKitTests/ForeignKeyConstraintTests.swift b/Tests/SQLiteDataTests/CloudKitTests/ForeignKeyConstraintTests.swift index cc2883d6..9596a66e 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/ForeignKeyConstraintTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/ForeignKeyConstraintTests.swift @@ -119,10 +119,13 @@ @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) @Test func remoteCreatesRecordABC_localReceivesAC_remoteDeletesBC() async throws { let modelARecord = CKRecord(recordType: ModelA.tableName, recordID: ModelA.recordID(for: 1)) + modelARecord.setValue(1, forKey: "id", at: now) let modelBRecord = CKRecord(recordType: ModelB.tableName, recordID: ModelB.recordID(for: 1)) + modelBRecord.setValue(1, forKey: "id", at: now) modelBRecord.setValue(1, forKey: "modelAID", at: now) modelBRecord.parent = CKRecord.Reference(record: modelARecord, action: .none) let modelCRecord = CKRecord(recordType: ModelC.tableName, recordID: ModelC.recordID(for: 1)) + modelCRecord.setValue(1, forKey: "id", at: now) modelCRecord.setValue(1, forKey: "modelBID", at: now) modelCRecord.parent = CKRecord.Reference(record: modelBRecord, action: .none) @@ -205,7 +208,8 @@ recordID: CKRecord.ID(1:modelAs/zone/__defaultOwner__), recordType: "modelAs", parent: nil, - share: nil + share: nil, + id: 1 ) ] ), diff --git a/Tests/SQLiteDataTests/CloudKitTests/MergeConflictTests.swift b/Tests/SQLiteDataTests/CloudKitTests/MergeConflictTests.swift index e3a5964a..c2e36742 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/MergeConflictTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/MergeConflictTests.swift @@ -33,10 +33,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 0, isCompleted🗓️: 0, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "", @@ -90,10 +92,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 0, isCompleted🗓️: 0, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "Buy milk", @@ -135,10 +139,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 1, isCompleted🗓️: 30, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "Buy milk", @@ -187,10 +193,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 0, isCompleted🗓️: 0, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "", @@ -244,10 +252,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 0, isCompleted🗓️: 0, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "Buy milk", @@ -289,10 +299,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 1, isCompleted🗓️: 60, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "Buy milk", @@ -358,10 +370,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 1, isCompleted🗓️: 60, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "Buy milk", @@ -445,10 +459,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 0, isCompleted🗓️: 0, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "Get milk", @@ -514,10 +530,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 0, isCompleted🗓️: 0, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "Get milk", @@ -584,10 +602,12 @@ recordType: "reminders", parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), share: nil, + dueDate🗓️: 0, id: 1, id🗓️: 0, isCompleted: 0, isCompleted🗓️: 0, + priority🗓️: 0, remindersListID: 1, remindersListID🗓️: 0, title: "Get milk", @@ -626,86 +646,90 @@ } try await syncEngine.processPendingRecordZoneChanges(scope: .private) - let reminderRecord = try syncEngine.private.database.record( - for: Reminder.recordID(for: 1) - ) - reminderRecord.setValue( - Date(timeIntervalSince1970: Double(now + 30)), - forKey: "dueDate", - at: now - ) - let modificationsFinished = try syncEngine.modifyRecords( - scope: .private, - saving: [reminderRecord] - ) - try await withDependencies { $0.currentTime.now += 1 } operation: { - try await userDatabase.userWrite { db in - try Reminder.find(1).update { $0.priority = 3 }.execute(db) + let reminderRecord = try syncEngine.private.database.record( + for: Reminder.recordID(for: 1) + ) + reminderRecord.setValue( + Date(timeIntervalSince1970: Double(30)), + forKey: "dueDate", + at: now + ) + let modificationsFinished = try syncEngine.modifyRecords( + scope: .private, + saving: [reminderRecord] + ) + + try await withDependencies { + $0.currentTime.now += 1 + } operation: { + 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( - privateCloudDatabase: MockCloudDatabase( - databaseScope: .private, - storage: [ - [0]: CKRecord( - recordID: CKRecord.ID(1:reminders/zone/__defaultOwner__), - recordType: "reminders", - parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), - share: nil, - dueDate: Date(1970-01-01T00:00:30.000Z), - dueDate🗓️: 0, - id: 1, - id🗓️: 0, - isCompleted: 0, - isCompleted🗓️: 0, - priority: 3, - priority🗓️: 1, - remindersListID: 1, - remindersListID🗓️: 0, - title: "", - title🗓️: 0, - 🗓️: 1 - ), - [1]: CKRecord( - recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), - recordType: "remindersLists", - parent: nil, - share: nil, - id: 1, - id🗓️: 0, - title: "Personal", - title🗓️: 0, - 🗓️: 0 - ) - ] - ), - sharedCloudDatabase: MockCloudDatabase( - databaseScope: .shared, - storage: [] + assertInlineSnapshot(of: container, as: .customDump) { + """ + MockCloudContainer( + privateCloudDatabase: MockCloudDatabase( + databaseScope: .private, + storage: [ + [0]: CKRecord( + recordID: CKRecord.ID(1:reminders/zone/__defaultOwner__), + recordType: "reminders", + parent: CKReference(recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__)), + share: nil, + dueDate: Date(1970-01-01T00:00:30.000Z), + dueDate🗓️: 1, + id: 1, + id🗓️: 0, + isCompleted: 0, + isCompleted🗓️: 0, + priority: 3, + priority🗓️: 2, + remindersListID: 1, + remindersListID🗓️: 0, + title: "", + title🗓️: 0, + 🗓️: 2 + ), + [1]: CKRecord( + recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), + recordType: "remindersLists", + parent: nil, + share: nil, + id: 1, + id🗓️: 0, + title: "Personal", + title🗓️: 0, + 🗓️: 0 + ) + ] + ), + sharedCloudDatabase: MockCloudDatabase( + databaseScope: .shared, + storage: [] + ) ) - ) - """ - } + """ + } - try await userDatabase.read { db in - let reminder = try #require(try Reminder.find(1).fetchOne(db)) - #expect( - reminder - == Reminder( + try await userDatabase.read { db in + let reminder = try #require(try Reminder.find(1).fetchOne(db)) + expectNoDifference( + reminder, + Reminder( id: 1, dueDate: Date(timeIntervalSince1970: 30), priority: 3, remindersListID: 1 ) - ) + ) + } } } } diff --git a/Tests/SQLiteDataTests/CloudKitTests/MockCloudDatabaseTests.swift b/Tests/SQLiteDataTests/CloudKitTests/MockCloudDatabaseTests.swift index ecd50cc2..d019ae9e 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/MockCloudDatabaseTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/MockCloudDatabaseTests.swift @@ -46,6 +46,30 @@ #expect(error == CKError(.unknownItem)) } + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + @Test func assetsUseTemporaryDirectory() async throws { + let recordID = CKRecord.ID(recordName: "record") + let record = CKRecord(recordType: "Record", recordID: recordID) + let sourceURL = URL(fileURLWithPath: "/sqlite-data-test-assets/asset.jpg") + try inMemoryDataManager.save(Data("image".utf8), to: sourceURL) + record["asset"] = CKAsset(fileURL: sourceURL) + + let database = syncEngine.private.database + let (saveResults, _) = try database.modifyRecords( + saving: [record], + deleting: [] + ) + _ = try saveResults[recordID]?.get() + + let fetched = try database.record(for: recordID) + let asset = fetched["asset"] as? CKAsset + let assetDirectory = try #require(asset?.fileURL?.path()) + #expect( + assetDirectory + .hasPrefix(inMemoryDataManager.temporaryDirectory.path()) + ) + } + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) @Test func saveTransaction_ChildBeforeParent() async throws { let parent = CKRecord(recordType: "A", recordID: CKRecord.ID(recordName: "A")) diff --git a/Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift b/Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift index b36cbd8a..098eafb1 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift @@ -262,6 +262,71 @@ """ } } + + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + @Test(.printTimestamps(true), .printRecordChangeTag) + func editBetweenBatchAndSentRecordZoneChanges() async throws { + try await userDatabase.userWrite { db in + try db.seed { + RemindersList(id: 1, title: "Personal") + } + } + try await syncEngine.processPendingRecordZoneChanges(scope: .private) + + try await withDependencies { + $0.currentTime.now += 1 + } operation: { + try await userDatabase.userWrite { db in + try RemindersList.find(1).update { $0.title = "Personal 2" }.execute(db) + } + + let changes = try await syncEngine.sendPendingRecordZoneChanges(scope: .private) + + try await withDependencies { + $0.currentTime.now += 1 + } operation: { + try await userDatabase.userWrite { db in + try RemindersList.find(1).update { $0.title = "Personal 3" }.execute(db) + } + await changes.receive() + try await syncEngine.processPendingRecordZoneChanges(scope: .private) + + try await userDatabase.read { db in + expectNoDifference( + try RemindersList.fetchAll(db), + [RemindersList(id: 1, title: "Personal 3")] + ) + } + assertInlineSnapshot(of: syncEngine.container, as: .customDump) { + """ + MockCloudContainer( + privateCloudDatabase: MockCloudDatabase( + databaseScope: .private, + storage: [ + [0]: CKRecord( + recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), + recordType: "remindersLists", + parent: nil, + share: nil, + recordChangeTag: 3, + id: 1, + id🗓️: 0, + title: "Personal 3", + title🗓️: 2, + 🗓️: 2 + ) + ] + ), + sharedCloudDatabase: MockCloudDatabase( + databaseScope: .shared, + storage: [] + ) + ) + """ + } + } + } + } } } diff --git a/Tests/SQLiteDataTests/CloudKitTests/PreviewTests.swift b/Tests/SQLiteDataTests/CloudKitTests/PreviewTests.swift index 10dffa67..3eabc637 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/PreviewTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/PreviewTests.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if DEBUG && canImport(DeveloperToolsSupport) && canImport(CloudKit) import DependenciesTestSupport import InlineSnapshotTesting import SnapshotTestingCustomDump @@ -43,9 +43,8 @@ } } - @Test @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) - func delete() async throws { + @Test func delete() async throws { @FetchAll(RemindersList.all, database: userDatabase.database) var remindersLists try await userDatabase.userWrite { db in diff --git a/Tests/SQLiteDataTests/CloudKitTests/RecordTypeTests.swift b/Tests/SQLiteDataTests/CloudKitTests/RecordTypeTests.swift index a7190930..8e624b72 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/RecordTypeTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/RecordTypeTests.swift @@ -22,7 +22,7 @@ tableName: "remindersLists", schema: """ CREATE TABLE "remindersLists" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "title" TEXT NOT NULL ON CONFLICT REPLACE DEFAULT '' ) STRICT """, @@ -32,7 +32,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: "\'\'", @@ -99,7 +99,7 @@ tableName: "reminders", schema: """ CREATE TABLE "reminders" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "dueDate" TEXT, "isCompleted" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "priority" INTEGER, @@ -122,7 +122,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [2]: TableInfo( defaultValue: "0", @@ -175,7 +175,7 @@ tableName: "reminderTags", schema: """ CREATE TABLE "reminderTags" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "reminderID" INTEGER NOT NULL REFERENCES "reminders"("id") ON DELETE CASCADE, "tagID" TEXT NOT NULL REFERENCES "tags"("title") ON DELETE CASCADE ON UPDATE CASCADE ) STRICT @@ -186,7 +186,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: nil, @@ -208,7 +208,7 @@ tableName: "parents", schema: """ CREATE TABLE "parents"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + "id" INT PRIMARY KEY NOT NULL ) STRICT """, tableInfo: [ @@ -217,7 +217,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ) ] ), @@ -225,7 +225,7 @@ tableName: "childWithOnDeleteSetNulls", schema: """ CREATE TABLE "childWithOnDeleteSetNulls"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "parentID" INTEGER REFERENCES "parents"("id") ON DELETE SET NULL ON UPDATE SET NULL ) STRICT """, @@ -235,7 +235,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: nil, @@ -250,7 +250,7 @@ tableName: "childWithOnDeleteSetDefaults", schema: """ CREATE TABLE "childWithOnDeleteSetDefaults"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "parentID" INTEGER NOT NULL DEFAULT 0 REFERENCES "parents"("id") ON DELETE SET DEFAULT ON UPDATE SET DEFAULT ) STRICT @@ -261,7 +261,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: "0", @@ -276,7 +276,7 @@ tableName: "modelAs", schema: """ CREATE TABLE "modelAs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "count" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "isEven" INTEGER GENERATED ALWAYS AS ("count" % 2 == 0) VIRTUAL ) @@ -294,7 +294,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ) ] ), @@ -302,7 +302,7 @@ tableName: "modelBs", schema: """ CREATE TABLE "modelBs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "isOn" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "modelAID" INTEGER NOT NULL REFERENCES "modelAs"("id") ON DELETE CASCADE ) @@ -313,7 +313,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: "0", @@ -335,7 +335,7 @@ tableName: "modelCs", schema: """ CREATE TABLE "modelCs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "title" TEXT NOT NULL ON CONFLICT REPLACE DEFAULT '', "modelBID" INTEGER NOT NULL REFERENCES "modelBs"("id") ON DELETE CASCADE ) @@ -346,7 +346,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [1]: TableInfo( defaultValue: nil, @@ -445,7 +445,7 @@ tableName: "reminders", schema: """ CREATE TABLE "reminders" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "dueDate" TEXT, "isCompleted" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "priority" INTEGER, @@ -468,7 +468,7 @@ isPrimaryKey: true, name: "id", isNotNull: true, - type: "INTEGER" + type: "INT" ), [2]: TableInfo( defaultValue: "0", diff --git a/Tests/SQLiteDataTests/CloudKitTests/SchemaChangeTests.swift b/Tests/SQLiteDataTests/CloudKitTests/SchemaChangeTests.swift index 735d3cb4..e2b96c39 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/SchemaChangeTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/SchemaChangeTests.swift @@ -218,7 +218,7 @@ try #sql( """ ALTER TABLE "remindersLists" - ADD COLUMN "position" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0 + ADD COLUMN "position" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 42 """ ) .execute(db) @@ -236,6 +236,220 @@ ], privateTables: syncEngine.privateTables ) + + try await userDatabase.read { db in + try #expect( + RemindersListWithPosition.fetchAll(db) == [ + RemindersListWithPosition(id: 1, title: "Personal", position: 42) + ] + ) + } + } + + /* + * Old schema creates record and synchronizes to iCloud. + * Schema is migrated to add a "NULL DEFAULT _" column. + * New sync engine is launched. + => Sync starts without emitting an error and default value is persisted in local database. + */ + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + @Test func addNullableColumn_OldRecordsSyncToNewSchema() async throws { + let remindersList = RemindersList(id: 1, title: "Personal") + try await userDatabase.userWrite { db in + try db.seed { + remindersList + } + } + try await syncEngine.processPendingRecordZoneChanges(scope: .private) + + syncEngine.stop() + + try await userDatabase.userWrite { db in + try #sql( + """ + ALTER TABLE "remindersLists" + ADD COLUMN "color" INTEGER DEFAULT 42 + """ + ) + .execute(db) + } + + // NB: Sync engine should start without emitting issue. + _ = try await SyncEngine( + container: syncEngine.container, + userDatabase: syncEngine.userDatabase, + tables: syncEngine.tables + .filter { $0.base != RemindersList.self } + + [ + SynchronizedTable(for: RemindersListWithColor.self), + ], + privateTables: syncEngine.privateTables + ) + + try await userDatabase.read { db in + try #expect( + RemindersListWithColor.fetchAll(db) == [ + RemindersListWithColor(id: 1, title: "Personal", color: 42) + ] + ) + } + } + + /* + * Schema is migrated to add a "NULL DEFAULT _" column. + * New sync engine is launched. + * Old record with no 'color' value synchronized + => Local database row created uses default for 'color'. + */ + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + @Test func addNullableColumn_OldDeviceSyncsMissingColor() async throws { + syncEngine.stop() + + try await userDatabase.userWrite { db in + try #sql( + """ + ALTER TABLE "remindersLists" + ADD COLUMN "color" INTEGER DEFAULT 42 + """ + ) + .execute(db) + } + + // NB: Sync engine should start without emitting issue. + let relaunchedSyncEngine = try await SyncEngine( + container: syncEngine.container, + userDatabase: syncEngine.userDatabase, + tables: syncEngine.tables + .filter { $0.base != RemindersList.self } + + [ + SynchronizedTable(for: RemindersListWithColor.self), + ], + privateTables: syncEngine.privateTables + ) + + try await withDependencies { + $0.currentTime.now += 1 + } operation: { + let remindersListRecord = CKRecord( + recordType: RemindersList.tableName, + recordID: RemindersList.recordID(for: 1) + ) + remindersListRecord.setValue(1, forKey: "id", at: now) + remindersListRecord.setValue("My stuff", forKey: "title", at: now) + try await relaunchedSyncEngine + .modifyRecords(scope: .private, saving: [remindersListRecord]) + .notify() + + try await userDatabase.read { db in + try #expect( + RemindersListWithColor.fetchAll(db) == [ + RemindersListWithColor(id: 1, title: "My stuff", color: 42) + ] + ) + } + assertInlineSnapshot(of: relaunchedSyncEngine.container, as: .customDump) { + """ + MockCloudContainer( + privateCloudDatabase: MockCloudDatabase( + databaseScope: .private, + storage: [ + [0]: CKRecord( + recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), + recordType: "remindersLists", + parent: nil, + share: nil, + id: 1, + title: "My stuff" + ) + ] + ), + sharedCloudDatabase: MockCloudDatabase( + databaseScope: .shared, + storage: [] + ) + ) + """ + } + } + } + + /* + * Schema is migrated to add a "NULL DEFAULT _" column. + * New sync engine is launched. + * New record with NULL 'color' value synchronized + => Local database row created uses NULL for color + */ + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + @Test func addNullableColumn_NewDeviceSyncsNullColor() async throws { + syncEngine.stop() + + try await userDatabase.userWrite { db in + try #sql( + """ + ALTER TABLE "remindersLists" + ADD COLUMN "color" INTEGER DEFAULT 42 + """ + ) + .execute(db) + } + + // NB: Sync engine should start without emitting issue. + let relaunchedSyncEngine = try await SyncEngine( + container: syncEngine.container, + userDatabase: syncEngine.userDatabase, + tables: syncEngine.tables + .filter { $0.base != RemindersList.self } + + [ + SynchronizedTable(for: RemindersListWithColor.self), + ], + privateTables: syncEngine.privateTables + ) + + try await withDependencies { + $0.currentTime.now += 1 + } operation: { + let remindersListRecord = CKRecord( + recordType: RemindersList.tableName, + recordID: RemindersList.recordID(for: 1) + ) + remindersListRecord.setValue(1, forKey: "id", at: now) + remindersListRecord.setValue("My stuff", forKey: "title", at: now) + remindersListRecord.removeValue(forKey: "color", at: now) + try await relaunchedSyncEngine + .modifyRecords(scope: .private, saving: [remindersListRecord]) + .notify() + + try await userDatabase.read { db in + try #expect( + RemindersListWithColor.fetchAll(db) == [ + RemindersListWithColor(id: 1, title: "My stuff", color: nil) + ] + ) + } + assertInlineSnapshot(of: relaunchedSyncEngine.container, as: .customDump) { + """ + MockCloudContainer( + privateCloudDatabase: MockCloudDatabase( + databaseScope: .private, + storage: [ + [0]: CKRecord( + recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), + recordType: "remindersLists", + parent: nil, + share: nil, + id: 1, + title: "My stuff" + ) + ] + ), + sharedCloudDatabase: MockCloudDatabase( + databaseScope: .shared, + storage: [] + ) + ) + """ + } + } } /* @@ -632,6 +846,7 @@ saving: [imageRecord] ) .notify() + syncEngine.stop() inMemoryDataManager.storage.withValue { $0.removeAll() } @@ -656,26 +871,90 @@ ) defer { _ = relaunchedSyncEngine } - let images = try await userDatabase.read { db in - try Image.order(by: \.id).fetchAll(db) + try await userDatabase.read { db in + expectNoDifference( + try Image.order(by: \.id).fetchAll(db), + [ + Image(id: 1, image: Data("image".utf8), caption: "A good image") + ] + ) } - expectNoDifference( - images, - [ - Image(id: 1, image: Data("image".utf8), caption: "A good image") - ] + assertInlineSnapshot(of: relaunchedSyncEngine.container, as: .customDump) { + """ + MockCloudContainer( + privateCloudDatabase: MockCloudDatabase( + databaseScope: .private, + storage: [ + [0]: CKRecord( + recordID: CKRecord.ID(1:images/zone/__defaultOwner__), + recordType: "images", + parent: nil, + share: nil, + caption: "A good image", + id: "1", + image: Data(5 bytes) + ) + ] + ), + sharedCloudDatabase: MockCloudDatabase( + databaseScope: .shared, + storage: [] + ) + ) + """ + } + } + } + + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + @Test func outsideRecord() async throws { + let customRecord = CKRecord( + recordType: "customRecord", + recordID: CKRecord.ID( + recordName: "customRecord", + zoneID: SyncEngine.defaultTestZone.zoneID + ) + ) + try await syncEngine.modifyRecords(scope: .private, saving: [customRecord]).notify() + assertQuery(SyncMetadata.all, database: syncEngine.metadatabase) { + """ + (No results) + """ + } + } + + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + @Test func outsideRecordWithColon() async throws { + let customRecord = CKRecord( + recordType: "customRecord", + recordID: CKRecord.ID( + recordName: "1:customRecord", + zoneID: SyncEngine.defaultTestZone.zoneID ) + ) + try await syncEngine.modifyRecords(scope: .private, saving: [customRecord]).notify() + assertQuery(SyncMetadata.all, database: syncEngine.metadatabase) { + """ + (No results) + """ } } } } +@Table("remindersLists") +private struct RemindersListWithPosition: Equatable, Identifiable { + let id: Int + var title = "" + var position = 0 +} + @Table("remindersLists") - private struct RemindersListWithPosition: Equatable, Identifiable { + private struct RemindersListWithColor: Equatable, Identifiable { let id: Int var title = "" - var position = 0 + var color: Int? } @Table("reminders") diff --git a/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift b/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift index 6283c358..9d6705f4 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift @@ -307,14 +307,14 @@ """ } assertInlineSnapshot(of: error, as: .customDump) { - """ + #""" SyncEngine.SharingError( recordTableName: "remindersLists", recordPrimaryKey: "1", reason: .recordMetadataNotFound, - debugDescription: "No sync metadata found for record. Has the record been saved to the database?" + debugDescription: "No sync metadata found for record. Has the record been saved to the database and synchronized to iCloud? Invoke \'SyncEngine.sendChanges()\' to force synchronization." ) - """ + """# } } @@ -1592,6 +1592,7 @@ recordType: ModelA.tableName, recordID: ModelA.recordID(for: 1, zoneID: externalZone.zoneID) ) + modelARecord.setValue(1, forKey: "id", at: now) modelARecord.setValue(42, forKey: "count", at: now) let share = CKShare( @@ -1657,7 +1658,8 @@ recordType: "modelAs", parent: nil, share: CKReference(recordID: CKRecord.ID(share-1:modelAs/external.zone/external.owner)), - count: 42 + count: 42, + id: 1 ), [1]: CKRecord( recordID: CKRecord.ID(1:modelBs/external.zone/external.owner), diff --git a/Tests/SQLiteDataTests/CloudKitTests/SyncEngineTests.swift b/Tests/SQLiteDataTests/CloudKitTests/SyncEngineTests.swift index 04cada76..1a695fcb 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/SyncEngineTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/SyncEngineTests.swift @@ -93,6 +93,28 @@ """ ) } + + @Test func isSynchronizingTriggerWarning() { + withKnownIssue { + _ = Reminder.createTemporaryTrigger( + after: .insert { new in + Values(SyncEngine.isSynchronizing) + } + ) + } matching: { issue in + issue.description.hasSuffix( + """ + Invoked 'SyncEngine.isSynchronizing' at trigger creation, which is unexpected. Use \ + 'SyncEngine.$isSynchronizing' to invoke at trigger execution, instead. + """ + ) + } + _ = Reminder.createTemporaryTrigger( + after: .insert { new in + Values(SyncEngine.$isSynchronizing) + } + ) + } } } diff --git a/Tests/SQLiteDataTests/CloudKitTests/TriggerTests.swift b/Tests/SQLiteDataTests/CloudKitTests/TriggerTests.swift index bc4c1ec2..4a04e1b2 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/TriggerTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/TriggerTests.swift @@ -23,7 +23,7 @@ AFTER DELETE ON "childWithOnDeleteSetDefaults" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetDefaults')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetDefaults'))); END """, [1]: """ @@ -33,7 +33,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -41,10 +41,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetDefaults')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetDefaults'))); END """, [2]: """ @@ -52,7 +52,7 @@ AFTER DELETE ON "childWithOnDeleteSetNulls" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetNulls')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetNulls'))); END """, [3]: """ @@ -62,7 +62,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -70,10 +70,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetNulls')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetNulls'))); END """, [4]: """ @@ -81,7 +81,7 @@ AFTER DELETE ON "modelAs" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs'))); END """, [5]: """ @@ -91,7 +91,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -99,10 +99,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs'))); END """, [6]: """ @@ -110,7 +110,7 @@ AFTER DELETE ON "modelBs" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs'))); END """, [7]: """ @@ -120,7 +120,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelAs')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelAs'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -128,10 +128,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs'))); END """, [8]: """ @@ -139,7 +139,7 @@ AFTER DELETE ON "modelCs" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelCs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelCs'))); END """, [9]: """ @@ -149,7 +149,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelBs')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelBs'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -157,10 +157,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelCs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelCs'))); END """, [10]: """ @@ -168,7 +168,7 @@ AFTER DELETE ON "parents" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))); END """, [11]: """ @@ -178,7 +178,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -186,10 +186,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))); END """, [12]: """ @@ -197,7 +197,7 @@ AFTER DELETE ON "reminderTags" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminderTags')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminderTags'))); END """, [13]: """ @@ -207,7 +207,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -215,10 +215,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminderTags')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminderTags'))); END """, [14]: """ @@ -226,7 +226,7 @@ AFTER DELETE ON "remindersListAssets" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListAssets')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListAssets'))); END """, [15]: """ @@ -236,7 +236,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -244,10 +244,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListAssets')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListAssets'))); END """, [16]: """ @@ -255,7 +255,7 @@ AFTER DELETE ON "remindersListPrivates" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListPrivates')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListPrivates'))); END """, [17]: """ @@ -265,7 +265,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -273,10 +273,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListPrivates')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListPrivates'))); END """, [18]: """ @@ -284,7 +284,7 @@ AFTER DELETE ON "remindersLists" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))); END """, [19]: """ @@ -294,7 +294,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -302,10 +302,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))); END """, [20]: """ @@ -313,7 +313,7 @@ AFTER DELETE ON "reminders" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminders')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminders'))); END """, [21]: """ @@ -323,7 +323,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -331,10 +331,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminders')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminders'))); END """, [22]: """ @@ -345,7 +345,7 @@ 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") + 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" @@ -353,7 +353,7 @@ ) SELECT "ancestorMetadatas"."lastKnownServerRecord" FROM "ancestorMetadatas" - WHERE ("ancestorMetadatas"."parentRecordName") IS (NULL) + WHERE (("ancestorMetadatas"."parentRecordName") IS (NULL)) )), "new"."share"); END """, @@ -362,7 +362,7 @@ AFTER DELETE ON "tags" FOR EACH ROW WHEN "sqlitedata_icloud_syncEngineIsSynchronizingChanges"() BEGIN DELETE FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."title")) AND (("sqlitedata_icloud_metadata"."recordType") = ('tags')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."title")) AND (("sqlitedata_icloud_metadata"."recordType") = ('tags'))); END """, [24]: """ @@ -372,7 +372,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -380,10 +380,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."title")) AND (("sqlitedata_icloud_metadata"."recordType") = ('tags')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."title")) AND (("sqlitedata_icloud_metadata"."recordType") = ('tags'))); END """, [25]: """ @@ -393,7 +393,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -401,14 +401,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))))), 'zone'), coalesce(coalesce(NULL, "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' + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))))), '__defaultOwner__'), "new"."parentID", 'parents' ON CONFLICT DO NOTHING; END """, @@ -419,7 +419,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -427,14 +427,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))))), 'zone'), coalesce(coalesce(NULL, "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' + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))))), '__defaultOwner__'), "new"."parentID", 'parents' ON CONFLICT DO NOTHING; END """, @@ -445,7 +445,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -453,7 +453,7 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL @@ -467,7 +467,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelAs')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelAs'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -475,14 +475,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs'))))), 'zone'), coalesce(coalesce(NULL, "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' + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs'))))), '__defaultOwner__'), "new"."modelAID", 'modelAs' ON CONFLICT DO NOTHING; END """, @@ -493,7 +493,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelBs')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelBs'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -501,14 +501,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(coalesce(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs'))))), 'zone'), coalesce(coalesce(NULL, "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' + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs'))))), '__defaultOwner__'), "new"."modelBID", 'modelBs' ON CONFLICT DO NOTHING; END """, @@ -519,7 +519,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -527,7 +527,7 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL @@ -541,7 +541,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -549,7 +549,7 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL @@ -563,7 +563,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -571,14 +571,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), 'zone'), coalesce(coalesce(NULL, "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' + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists' ON CONFLICT DO NOTHING; END """, @@ -589,7 +589,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -597,14 +597,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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"."remindersListID", 'remindersListAssets', coalesce(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), 'zone'), coalesce(coalesce(NULL, "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' + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists' ON CONFLICT DO NOTHING; END """, @@ -615,7 +615,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -623,14 +623,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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"."remindersListID", 'remindersListPrivates', coalesce(coalesce('zone', "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('__defaultOwner__', "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), 'zone'), coalesce(coalesce('__defaultOwner__', "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' + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), '__defaultOwner__'), "new"."remindersListID", 'remindersLists' ON CONFLICT DO NOTHING; END """, @@ -641,7 +641,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -649,7 +649,7 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL @@ -672,7 +672,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -680,7 +680,7 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', coalesce("sqlitedata_icloud_currentZoneName"(), 'zone'), coalesce("sqlitedata_icloud_currentOwnerName"(), '__defaultOwner__'), NULL, NULL @@ -694,7 +694,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -702,10 +702,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetDefaults')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetDefaults'))); END """, [39]: """ @@ -715,7 +715,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -723,10 +723,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetNulls')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('childWithOnDeleteSetNulls'))); END """, [40]: """ @@ -736,7 +736,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -744,10 +744,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs'))); END """, [41]: """ @@ -757,7 +757,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelAs')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelAs'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -765,10 +765,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs'))); END """, [42]: """ @@ -778,7 +778,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelBs')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelBs'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -786,10 +786,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelCs')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelCs'))); END """, [43]: """ @@ -799,7 +799,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -807,10 +807,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))); END """, [44]: """ @@ -820,7 +820,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -828,10 +828,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminderTags')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminderTags'))); END """, [45]: """ @@ -841,7 +841,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -849,10 +849,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminders')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminders'))); END """, [46]: """ @@ -862,7 +862,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -870,10 +870,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListAssets')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListAssets'))); END """, [47]: """ @@ -883,7 +883,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -891,10 +891,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListPrivates')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListPrivates'))); END """, [48]: """ @@ -904,7 +904,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -912,10 +912,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))); END """, [49]: """ @@ -925,7 +925,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -933,10 +933,10 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + WHERE (((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share")))); UPDATE "sqlitedata_icloud_metadata" SET "_isDeleted" = 1 - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."title")) AND (("sqlitedata_icloud_metadata"."recordType") = ('tags')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("old"."title")) AND (("sqlitedata_icloud_metadata"."recordType") = ('tags'))); END """, [50]: """ @@ -946,7 +946,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -954,22 +954,22 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))))), 'zone'), coalesce(coalesce(NULL, "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' + 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(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (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(NULL, "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')); + 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 """, [51]: """ @@ -979,7 +979,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('parents'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -987,22 +987,22 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."parentID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))))), 'zone'), coalesce(coalesce(NULL, "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' + 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(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (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(NULL, "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") = ('childWithOnDeleteSetNulls')); + 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 """, [52]: """ @@ -1012,7 +1012,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1020,14 +1020,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', 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')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs'))); END """, [53]: """ @@ -1037,7 +1037,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelAs')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelAs'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1045,22 +1045,22 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."modelAID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelAs'))))), 'zone'), coalesce(coalesce(NULL, "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' + 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(NULL, "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')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce(NULL, "sqlitedata_icloud_currentOwnerName"(), (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(NULL, "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')))), "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')); + 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 """, [54]: """ @@ -1070,7 +1070,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelBs')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('modelBs'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1078,22 +1078,22 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(coalesce(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs'))))), 'zone'), coalesce(coalesce(NULL, "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' + 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(NULL, "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')))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."modelBID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('modelBs'))))), "sqlitedata_icloud_metadata"."zoneName"), "ownerName" = coalesce(coalesce(NULL, "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')); + 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 """, [55]: """ @@ -1103,7 +1103,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1111,14 +1111,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', 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')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('parents'))); END """, [56]: """ @@ -1128,7 +1128,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1136,14 +1136,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', 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')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('reminderTags'))); END """, [57]: """ @@ -1153,7 +1153,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1161,22 +1161,22 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), 'zone'), coalesce(coalesce(NULL, "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' + 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(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (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(NULL, "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") = ('reminders')); + 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 """, [58]: """ @@ -1186,7 +1186,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1194,22 +1194,22 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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"."remindersListID", 'remindersListAssets', coalesce(coalesce(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), 'zone'), coalesce(coalesce(NULL, "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' + 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(NULL, "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(NULL, "sqlitedata_icloud_currentOwnerName"(), (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(NULL, "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"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListAssets')); + 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"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListAssets'))); END """, [59]: """ @@ -1219,7 +1219,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists')) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") IS ('remindersLists'))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1227,22 +1227,22 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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"."remindersListID", 'remindersListPrivates', coalesce(coalesce('zone', "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('__defaultOwner__', "sqlitedata_icloud_currentOwnerName"(), (SELECT "sqlitedata_icloud_metadata"."ownerName" + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))))), 'zone'), coalesce(coalesce('__defaultOwner__', "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' + 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('zone', "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('__defaultOwner__', "sqlitedata_icloud_currentOwnerName"(), (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('__defaultOwner__', "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"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListPrivates')); + 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"."remindersListID")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersListPrivates'))); END """, [60]: """ @@ -1252,7 +1252,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1260,14 +1260,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', 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')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."id")) AND (("sqlitedata_icloud_metadata"."recordType") = ('remindersLists'))); END """, [61]: """ @@ -1280,7 +1280,7 @@ WITH "descendantMetadatas" AS ( SELECT "sqlitedata_icloud_metadata"."recordName" AS "recordName", NULL AS "parentRecordName" FROM "sqlitedata_icloud_metadata" - WHERE ("sqlitedata_icloud_metadata"."recordName") = ("new"."recordName") + 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" @@ -1288,7 +1288,7 @@ ) SELECT json_group_array("descendantMetadatas"."recordName") FROM "descendantMetadatas" - WHERE ("descendantMetadatas"."recordName") <> ("new"."recordName") + WHERE (("descendantMetadatas"."recordName") <> ("new"."recordName")) ) END); END """, @@ -1299,7 +1299,7 @@ WITH "rootShares" AS ( SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" - WHERE (("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL)) + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") IS (NULL)) AND (("sqlitedata_icloud_metadata"."recordType") IS (NULL))) UNION ALL SELECT "sqlitedata_icloud_metadata"."parentRecordName" AS "parentRecordName", "sqlitedata_icloud_metadata"."share" AS "share" FROM "sqlitedata_icloud_metadata" @@ -1307,14 +1307,14 @@ ) SELECT RAISE(ABORT, 'co.pointfree.SQLiteData.CloudKit.write-permission-error') FROM "rootShares" - WHERE ((NOT ("sqlitedata_icloud_syncEngineIsSynchronizingChanges"())) AND (("rootShares"."parentRecordName") IS (NULL))) AND (NOT ("sqlitedata_icloud_hasPermission"("rootShares"."share"))); + 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', 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')); + WHERE ((("sqlitedata_icloud_metadata"."recordPrimaryKey") = ("new"."title")) AND (("sqlitedata_icloud_metadata"."recordType") = ('tags'))); END """, [63]: """ @@ -1323,17 +1323,17 @@ 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 ( + 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") + 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")); + FROM "descendantMetadatas"))); END """ ] diff --git a/Tests/SQLiteDataTests/CloudKitTests/UserlandTests.swift b/Tests/SQLiteDataTests/CloudKitTests/UserlandTests.swift index e5ad0bcd..4f755037 100644 --- a/Tests/SQLiteDataTests/CloudKitTests/UserlandTests.swift +++ b/Tests/SQLiteDataTests/CloudKitTests/UserlandTests.swift @@ -26,7 +26,7 @@ @FetchAll var modelAs: [ModelA] = [] try await database.write { db in try db.seed { - ModelA.Draft() + ModelA.Draft(id: 1) } } try await $modelAs.load() diff --git a/Tests/SQLiteDataTests/DateTests.swift b/Tests/SQLiteDataTests/DateTests.swift new file mode 100644 index 00000000..5415a916 --- /dev/null +++ b/Tests/SQLiteDataTests/DateTests.swift @@ -0,0 +1,51 @@ +import DependenciesTestSupport +import Foundation +import SQLiteData +import SQLiteDataTestSupport +import Testing + +@Suite(.dependency(\.defaultDatabase, try .database())) +struct DateTests { + @Dependency(\.defaultDatabase) var database + + @Test func roundtrip() throws { + let date = Date(timeIntervalSinceReferenceDate: 793109282.061) + let insertedRecord = try database.write { db in + try Record.insert { Record.Draft(date: date) } + .returning(\.self) + .fetchOne(db)! + } + let updatedRecord = try database.write { db in + try Record + .update(insertedRecord) + .returning(\.self) + .fetchOne(db)! + } + #expect(insertedRecord.date == date) + #expect(insertedRecord.date == updatedRecord.date) + } +} + +@Table +private struct Record: Equatable { + let id: Int + var date: Date +} + +extension DatabaseWriter where Self == DatabaseQueue { + fileprivate static func database() throws -> DatabaseQueue { + let database = try DatabaseQueue() + try database.write { db in + try #sql( + """ + CREATE TABLE "records" ( + "id" INTEGER PRIMARY KEY AUTOINCREMENT, + "date" TEXT NOT NULL + ) STRICT + """ + ) + .execute(db) + } + return database + } +} diff --git a/Tests/SQLiteDataTests/Internal/CloudKit+CustomDump.swift b/Tests/SQLiteDataTests/Internal/CloudKit+CustomDump.swift index 36ae5fc8..338db9df 100644 --- a/Tests/SQLiteDataTests/Internal/CloudKit+CustomDump.swift +++ b/Tests/SQLiteDataTests/Internal/CloudKit+CustomDump.swift @@ -20,6 +20,7 @@ extension CKRecord { @TaskLocal static var printTimestamps = false + @TaskLocal static var printRecordChangeTag = false } @available(macOS 14, iOS 17, tvOS 17, watchOS 10, *) @@ -50,14 +51,18 @@ let nonEncryptedKeys = Set(allKeys()) .subtracting(encryptedValues.allKeys()) .subtracting(["_recordChangeTag"]) + var baseChildren = [ + ("recordID", recordID as Any), + ("recordType", recordType as Any), + ("parent", parent as Any), + ("share", share as Any), + ] + if Self.printRecordChangeTag { + baseChildren.append(("recordChangeTag", _recordChangeTag as Any)) + } return Mirror( self, - children: [ - ("recordID", recordID as Any), - ("recordType", recordType as Any), - ("parent", parent as Any), - ("share", share as Any), - ] + children: baseChildren + keys .map { $0.hasPrefix(CKRecord.userModificationTimeKey) diff --git a/Tests/SQLiteDataTests/Internal/PrintTimestampsScope.swift b/Tests/SQLiteDataTests/Internal/PrintTimestampsScope.swift deleted file mode 100644 index 067815c6..00000000 --- a/Tests/SQLiteDataTests/Internal/PrintTimestampsScope.swift +++ /dev/null @@ -1,28 +0,0 @@ -#if canImport(CloudKit) - import CloudKit - import Testing - - struct _PrintTimestampsScope: SuiteTrait, TestScoping, TestTrait { - let printTimestamps: Bool - init(_ printTimestamps: Bool = true) { - self.printTimestamps = printTimestamps - } - - func provideScope( - for test: Test, - testCase: Test.Case?, - performing function: @Sendable () async throws -> Void - ) async throws { - try await CKRecord.$printTimestamps.withValue(true) { - try await function() - } - } - } - - extension Trait where Self == _PrintTimestampsScope { - static var printTimestamps: Self { Self() } - static func printTimestamps(_ printTimestamps: Bool) -> Self { - Self(printTimestamps) - } - } -#endif diff --git a/Tests/SQLiteDataTests/Internal/Schema.swift b/Tests/SQLiteDataTests/Internal/Schema.swift index ba018d1c..a9e965b9 100644 --- a/Tests/SQLiteDataTests/Internal/Schema.swift +++ b/Tests/SQLiteDataTests/Internal/Schema.swift @@ -94,7 +94,7 @@ func database( try #sql( """ CREATE TABLE "remindersLists" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "title" TEXT NOT NULL ON CONFLICT REPLACE DEFAULT '' ) STRICT """ @@ -123,7 +123,7 @@ func database( try #sql( """ CREATE TABLE "reminders" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "dueDate" TEXT, "isCompleted" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "priority" INTEGER, @@ -146,7 +146,7 @@ func database( try #sql( """ CREATE TABLE "reminderTags" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "reminderID" INTEGER NOT NULL REFERENCES "reminders"("id") ON DELETE CASCADE, "tagID" TEXT NOT NULL REFERENCES "tags"("title") ON DELETE CASCADE ON UPDATE CASCADE ) STRICT @@ -156,7 +156,7 @@ func database( try #sql( """ CREATE TABLE "parents"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + "id" INT PRIMARY KEY NOT NULL ) STRICT """ ) @@ -164,7 +164,7 @@ func database( try #sql( """ CREATE TABLE "childWithOnDeleteSetNulls"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "parentID" INTEGER REFERENCES "parents"("id") ON DELETE SET NULL ON UPDATE SET NULL ) STRICT """ @@ -173,7 +173,7 @@ func database( try #sql( """ CREATE TABLE "childWithOnDeleteSetDefaults"( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "parentID" INTEGER NOT NULL DEFAULT 0 REFERENCES "parents"("id") ON DELETE SET DEFAULT ON UPDATE SET DEFAULT ) STRICT @@ -183,7 +183,7 @@ func database( try #sql( """ CREATE TABLE "localUsers" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "name" TEXT NOT NULL ON CONFLICT REPLACE DEFAULT '', "parentID" INTEGER REFERENCES "localUsers"("id") ON DELETE CASCADE ) STRICT @@ -193,7 +193,7 @@ func database( try #sql( """ CREATE TABLE "modelAs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "count" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "isEven" INTEGER GENERATED ALWAYS AS ("count" % 2 == 0) VIRTUAL ) @@ -203,7 +203,7 @@ func database( try #sql( """ CREATE TABLE "modelBs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "isOn" INTEGER NOT NULL ON CONFLICT REPLACE DEFAULT 0, "modelAID" INTEGER NOT NULL REFERENCES "modelAs"("id") ON DELETE CASCADE ) @@ -213,7 +213,7 @@ func database( try #sql( """ CREATE TABLE "modelCs" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "id" INT PRIMARY KEY NOT NULL, "title" TEXT NOT NULL ON CONFLICT REPLACE DEFAULT '', "modelBID" INTEGER NOT NULL REFERENCES "modelBs"("id") ON DELETE CASCADE ) @@ -223,7 +223,7 @@ func database( try #sql( """ CREATE TABLE "unsyncedModels" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + "id" INT PRIMARY KEY NOT NULL ) """ ) diff --git a/Tests/SQLiteDataTests/Internal/TestScopes.swift b/Tests/SQLiteDataTests/Internal/TestScopes.swift index 7c1c34e6..64b1f92f 100644 --- a/Tests/SQLiteDataTests/Internal/TestScopes.swift +++ b/Tests/SQLiteDataTests/Internal/TestScopes.swift @@ -126,4 +126,53 @@ Self(syncEngineDelegate: syncEngineDelegate) } } + + struct _PrintRecordChangeTag: SuiteTrait, TestScoping, TestTrait { + let printRecordChangeTag: Bool + init(_ printRecordChangeTag: Bool = true) { + self.printRecordChangeTag = printRecordChangeTag + } + + func provideScope( + for test: Test, + testCase: Test.Case?, + performing function: @Sendable () async throws -> Void + ) async throws { + try await CKRecord.$printRecordChangeTag.withValue(true) { + try await function() + } + } + } + + extension Trait where Self == _PrintRecordChangeTag { + static var printRecordChangeTag: Self { Self() } + static func printRecordChangeTag(_ printRecordChangeTag: Bool) -> Self { + Self(printRecordChangeTag) + } + } + + struct _PrintTimestampsScope: SuiteTrait, TestScoping, TestTrait { + let printTimestamps: Bool + init(_ printTimestamps: Bool = true) { + self.printTimestamps = printTimestamps + } + + func provideScope( + for test: Test, + testCase: Test.Case?, + performing function: @Sendable () async throws -> Void + ) async throws { + try await CKRecord.$printTimestamps.withValue(true) { + try await function() + } + } + } + + extension Trait where Self == _PrintTimestampsScope { + static var printTimestamps: Self { Self() } + static func printTimestamps(_ printTimestamps: Bool) -> Self { + Self(printTimestamps) + } + } + #endif diff --git a/Tests/SQLiteDataTests/PrimaryKeyMigrationTests.swift b/Tests/SQLiteDataTests/PrimaryKeyMigrationTests.swift index 6435d68a..3e451803 100644 --- a/Tests/SQLiteDataTests/PrimaryKeyMigrationTests.swift +++ b/Tests/SQLiteDataTests/PrimaryKeyMigrationTests.swift @@ -1,3 +1,6 @@ +// NB: migratePrimaryKeys is disabled on Swift 6.2.3+ due to compiler crash +// See: Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift +#if !compiler(>=6.2.3) import DependenciesTestSupport import Foundation import InlineSnapshotTesting @@ -1221,3 +1224,4 @@ extension SQLiteSchema { .where { !$0.name.hasPrefix("sqlite_") } .order(by: \.name) } +#endif // !compiler(>=6.2.3)