Repository navigation
fix(copy): defer foreign key checks to the commit for a whole copy - #3859
Merged
Merged
Conversation
…ck a failed structure phase
…eep each batch under the other settings
… a no-transaction target kept
…arget first, and count a thrown cancellation
# Conflicts: # apple/TablePro/Core/ObjectCopy/ObjectCopyPlan.swift # apple/TablePro/Core/ObjectCopy/ObjectCopyPlanner.swift
…at transaction only
…on-level value is not readable under SET LOCAL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PluginSessionPurpose.relaxedForeignKeyssession scope: the driver turns off the target's foreign key checks for that session, and closing it puts back the setting the session had. MySQL and MariaDB implement it; PostgreSQL does not, sincesession_replication_rolealso stops user triggers and needs a superuser.ObjectCopyPlanner.keysInside). Otherwise they stay on: turning them back on checks nothing already written, and a table the target keeps (Data only, Add rows to it) may hold keys the source cannot speak for.ObjectCopyPlanner.keyChecks, one anti-join per key in the target's quoting). A source row whose parent is gone, or one read while the source was changing, fails the copy and rolls it back instead of committing past keys nothing checks again. The checks run once on the still-empty tables before the relax; an account that cannot run them keeps enforcement on.ON DELETErule. A table whose clear failed gets no rows.CREATE SCHEMAon PostgreSQL left the next lease inside an aborted transaction.Shopandshopare two MySQL databases..preservesavesforeign_keys, and.relaxedForeignKeysreturns nil inside a transaction, where the pragma is a no-op. A relax whose read-back fails turnsforeign_keysback on. SQL import already held.preserve; Save now holds it around its prologue, outside the user's transaction only: inside one the pragma does nothing, and PostgreSQL would put aSET LOCALvalue back session-wide. Neither leaves a SQLite connection enforcing foreign keys afterwards.SET session_replication_roleruns in aDOblock that swallowsinsufficient_privilege, so a non-superuser import or save no longer fails or aborts the open transaction.Test plan
ObjectCopyTransactionTestswith separate source and target drivers: relax on the target only, after the clears, closed on throw and cancel, none under a session transaction; keys outside the copy keep the checks (keysOutsideTheCopyKeepTheChecks,creationRelaxesOnlyInsideTheCopy); every table in one transaction under Stop and roll back (rollbackRunsTheRowsInOneTransaction); Stop and keep what ran commits each batch and counts what a failure kept (stopAndKeepCommitsEachBatch); a rollback counts nothing and a target with no transactions counts what it kept (rolledBackFailureCountsNothing,untransactionalTargetCountsWhatItKept); keys are checked before commit and a broken one rolls back, and one the account cannot run keeps the checks (relaxedCopyChecksKeysBeforeCommit,brokenKeyRollsTheCopyBack,uncheckableKeyKeepsTheChecks); target leased first (leasesTheTargetFirst); a MyISAM-style table keeps its count through a rollback (tableThatCannotRollBackKeepsItsCount); a thrown cancellation keeps its count (thrownCancellationKeepsTheCount); a failed clear gets no rows; a failed schema rolls back (failedSchemaRollsBack).ObjectCopyPlannerOrderingTests(ordering,keysInside,keyChecks),ObjectCopyPlannerStructureReadTests,CompareForeignKeyOrderTests,SQLiteSessionScopeTests(SQLiteDriverTests and TableProPluginKitTests),MySQLSessionScopeTests,PostgreSQLSessionScopeSQLTests,DataWriteExecutorTests/planWithoutPrologueOpensNoScopeandsaveInsideTheUsersTransactionOpensNoScope.ObjectCopyDDLSessionTests(5 cases),ObjectCopySessionScopeTests/runnerPinsSameEngineCopyandrunnerLeavesCrossEngineCopyUnscoped,DataWriteExecutorTeststogglesRunOutsideTheTransaction,togglesRunAfterRollback,aRequiredPrologueThatFailsStopsTheRunBeforeAnyStep.AppearancePaneListTests/themesListHoldsStillWhileAccessibilityReadsItandGutterNumberOffsetTests/windowGutterKeepsItsMargin, which fail on main on this Mac too (locked screen, Dark Mode).Screenshots
The configure step of the Copy To sheet, rendered from the test host (the Mac was locked, so XCUITest could not drive it).
Fixes #3858