Update datamodel upgrade logic for iOS to fix transaction and pragma conflicts (#1576)

This commit is contained in:
Leendert de Borst
2026-02-01 15:28:35 +01:00
committed by Leendert de Borst
parent c1aa28b295
commit eadcd97121
4 changed files with 38 additions and 9 deletions

View File

@@ -61,6 +61,10 @@
[vaultManager rollbackTransaction:resolve rejecter:reject];
}
- (void)persistAndMarkDirty:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
[vaultManager persistAndMarkDirty:resolve rejecter:reject];
}
- (void)getAuthMethods:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
[vaultManager getAuthMethods:resolve rejecter:reject];
}

View File

@@ -309,6 +309,17 @@ public class VaultManager: NSObject {
}
}
@objc
func persistAndMarkDirty(_ resolve: @escaping RCTPromiseResolveBlock,
rejecter reject: @escaping RCTPromiseRejectBlock) {
do {
try vaultStore.persistAndMarkDirty()
resolve(nil)
} catch {
reject("PERSIST_ERROR", "Failed to persist and mark dirty: \(error.localizedDescription)", error)
}
}
@objc
func deriveKeyFromPassword(_ password: String,
salt: String,

View File

@@ -2534,8 +2534,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
boost: 1dca942403ed9342f98334bf4c3621f011aa7946
DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385
boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
EXConstants: 98bcf0f22b820f9b28f9fee55ff2daededadd2f8
Expo: a64c53f1ebaa36c439a87874759b6690785e60a4
ExpoAsset: ef06e880126c375f580d4923fdd1cdf4ee6ee7d6
@@ -2558,8 +2558,8 @@ SPEC CHECKSUMS:
ExpoWebBrowser: dc39a88485f007e61a3dff05d6a75f22ab4a2e92
fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6
FBLazyVector: 07309209b7b914451b8f822544a18e2a0a85afff
fmt: 01b82d4ca6470831d1cc0852a1af644be019e8f6
glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
hermes-engine: 44bb6fe76a6eb400d3a992e2d0b21946ae999fa9
Macaw: 7af8ea57aa2cab35b4a52a45e6f85eea753ea9ae
OpenSSL-Universal: 6082b0bf950e5636fe0d78def171184e2b3899c2

View File

@@ -78,6 +78,9 @@ extension VaultStore {
}
/// Execute a raw SQL command on the database without parameters (for DDL operations like CREATE TABLE).
///
/// Note: Migration SQL scripts handle their own transactions and PRAGMA statements.
/// PRAGMA foreign_keys statements MUST be executed outside of transactions to take effect.
public func executeRaw(_ query: String) throws {
guard let dbConnection = self.dbConnection else {
throw NSError(domain: "VaultStore", code: 4, userInfo: [NSLocalizedDescriptionKey: "Database not initialized"])
@@ -89,14 +92,13 @@ extension VaultStore {
for statement in statements {
let trimmedStatement = statement.smartTrim()
// Skip empty statements and transaction control statements (handled externally)
if trimmedStatement.isEmpty ||
trimmedStatement.uppercased().hasPrefix("BEGIN TRANSACTION") ||
trimmedStatement.uppercased().hasPrefix("COMMIT") ||
trimmedStatement.uppercased().hasPrefix("ROLLBACK") {
// Skip empty statements and SQL comments
if trimmedStatement.isEmpty || trimmedStatement.hasPrefix("--") {
continue
}
// Execute all statements including PRAGMA and transaction control
// This allows migration SQL to properly control its own transactions and PRAGMA settings
try dbConnection.execute(trimmedStatement)
}
}
@@ -198,6 +200,18 @@ extension VaultStore {
try dbConnection.execute("ROLLBACK")
}
/// Persist the in-memory database to encrypted storage and mark as dirty.
/// Used after migrations where SQL handles its own transactions but we need to persist and sync.
/// This does NOT commit any SQL transaction - it just persists the current state of the database.
public func persistAndMarkDirty() throws {
try persistDatabaseToEncryptedStorage()
// Atomically mark vault as dirty and increment mutation sequence
// This ensures sync can properly detect local changes
setIsDirty(true)
_ = incrementMutationSequence()
}
// MARK: - Items (Using Repository Pattern)
/// Get all items from the database using the new field-based model.