feat: Implement comprehensive migration validation and integrity checking

- Add multi-layered migration validation strategy with schema detection
- Implement database integrity checker that validates all core tables and columns
- Add schema-based migration skipping to prevent re-running applied migrations
- Enhanced error handling for duplicate table/column scenarios with validation
- Add comprehensive logging for migration tracking and database state verification
- Include final validation step to ensure all migrations are properly recorded

The system now properly:
1. Checks if migrations are recorded in the migrations table
2. Validates actual schema exists before attempting to apply migrations
3. Handles edge cases where schema exists but isn't recorded
4. Provides detailed integrity checking of database structure
5. Eliminates SQL errors from duplicate table/column creation attempts

Migration tracking is now working correctly with both migrations properly recorded.
This commit is contained in:
Matthew Raymer
2025-06-30 07:15:20 +00:00
parent 4a01df509b
commit 70a9523f0a
2 changed files with 221 additions and 6 deletions

View File

@@ -286,7 +286,88 @@ export class CapacitorPlatformService implements PlatformService {
return new Set(names);
};
await runMigrations(sqlExec, sqlQuery, extractMigrationNames);
try {
await runMigrations(sqlExec, sqlQuery, extractMigrationNames);
// After migrations, run integrity check
await this.verifyDatabaseIntegrity();
} catch (error) {
console.error(`❌ [CapacitorMigration] Migration failed:`, error);
// Still try to verify what we have
await this.verifyDatabaseIntegrity();
throw error;
}
}
/**
* Verify database integrity and migration status
*/
private async verifyDatabaseIntegrity(): Promise<void> {
if (!this.db) {
console.error(`❌ [DB-Integrity] Database not initialized`);
return;
}
console.log(`🔍 [DB-Integrity] Starting database integrity check...`);
try {
// Check migrations table
const migrationsResult = await this.db.query("SELECT name, applied_at FROM migrations ORDER BY applied_at");
console.log(`📊 [DB-Integrity] Applied migrations:`, migrationsResult);
// Check core tables exist
const coreTableNames = ['accounts', 'secret', 'settings', 'contacts', 'logs', 'temp'];
const existingTables: string[] = [];
for (const tableName of coreTableNames) {
try {
const tableCheck = await this.db.query(`SELECT name FROM sqlite_master WHERE type='table' AND name='${tableName}'`);
if (tableCheck.values && tableCheck.values.length > 0) {
existingTables.push(tableName);
console.log(`✅ [DB-Integrity] Table ${tableName} exists`);
} else {
console.error(`❌ [DB-Integrity] Table ${tableName} missing`);
}
} catch (error) {
console.error(`❌ [DB-Integrity] Error checking table ${tableName}:`, error);
}
}
// Check contacts table schema (including iViewContent column)
if (existingTables.includes('contacts')) {
try {
const contactsSchema = await this.db.query("PRAGMA table_info(contacts)");
console.log(`📊 [DB-Integrity] Contacts table schema:`, contactsSchema);
const hasIViewContent = contactsSchema.values?.some((col: any) =>
(col.name === 'iViewContent') || (Array.isArray(col) && col[1] === 'iViewContent')
);
if (hasIViewContent) {
console.log(`✅ [DB-Integrity] iViewContent column exists in contacts table`);
} else {
console.error(`❌ [DB-Integrity] iViewContent column missing from contacts table`);
}
} catch (error) {
console.error(`❌ [DB-Integrity] Error checking contacts schema:`, error);
}
}
// Check for data integrity
try {
const accountCount = await this.db.query("SELECT COUNT(*) as count FROM accounts");
const settingsCount = await this.db.query("SELECT COUNT(*) as count FROM settings");
const contactsCount = await this.db.query("SELECT COUNT(*) as count FROM contacts");
console.log(`📊 [DB-Integrity] Data counts - Accounts: ${JSON.stringify(accountCount)}, Settings: ${JSON.stringify(settingsCount)}, Contacts: ${JSON.stringify(contactsCount)}`);
} catch (error) {
console.error(`❌ [DB-Integrity] Error checking data counts:`, error);
}
console.log(`✅ [DB-Integrity] Database integrity check completed`);
} catch (error) {
console.error(`❌ [DB-Integrity] Database integrity check failed:`, error);
}
}
/**