fix: resolve iOS migration 004 failure with enhanced error handling

- Fix multi-statement SQL execution issue in Capacitor SQLite
- Add individual statement execution for migration 004_active_identity_management
- Implement automatic recovery for missing active_identity table
- Enhance migration system with better error handling and logging

Problem:
Migration 004 was marked as applied but active_identity table wasn't created
due to multi-statement SQL execution failing silently in Capacitor SQLite.

Solution:
- Extended Migration interface with optional statements array
- Modified migration execution to handle individual statements
- Added bootstrapping hook recovery for missing tables
- Enhanced logging for better debugging

Files changed:
- src/services/migrationService.ts: Enhanced migration execution logic
- src/db-sql/migration.ts: Added recovery mechanism and individual statements

This fix ensures the app automatically recovers from the current broken state
and prevents similar issues in future migrations.
This commit is contained in:
Jose Olarte III
2025-09-16 20:14:58 +08:00
parent afe0f5e019
commit f31a76b816
2 changed files with 127 additions and 12 deletions

View File

@@ -73,6 +73,8 @@ interface Migration {
name: string;
/** SQL statement(s) to execute for this migration */
sql: string;
/** Optional array of individual SQL statements for better error handling */
statements?: string[];
}
/**
@@ -676,11 +678,30 @@ export async function runMigrations<T>(
try {
// Execute the migration SQL
migrationLog(`🔧 [Migration] Executing SQL for: ${migration.name}`);
migrationLog(`🔧 [Migration] SQL content: ${migration.sql}`);
const execResult = await sqlExec(migration.sql);
migrationLog(
`🔧 [Migration] SQL execution result: ${JSON.stringify(execResult)}`,
);
if (migration.statements && migration.statements.length > 0) {
// Execute individual statements for better error handling
migrationLog(
`🔧 [Migration] Executing ${migration.statements.length} individual statements`,
);
for (let i = 0; i < migration.statements.length; i++) {
const statement = migration.statements[i];
migrationLog(
`🔧 [Migration] Statement ${i + 1}/${migration.statements.length}: ${statement}`,
);
const execResult = await sqlExec(statement);
migrationLog(
`🔧 [Migration] Statement ${i + 1} result: ${JSON.stringify(execResult)}`,
);
}
} else {
// Execute as single SQL block (legacy behavior)
migrationLog(`🔧 [Migration] SQL content: ${migration.sql}`);
const execResult = await sqlExec(migration.sql);
migrationLog(
`🔧 [Migration] SQL execution result: ${JSON.stringify(execResult)}`,
);
}
// Validate the migration was applied correctly
const validation = await validateMigrationApplication(