fix: Remove old record_type CHECK constraint from health_records (Migration 003) #40
@@ -59,6 +59,20 @@ class MigrationRunner {
|
|||||||
return columns.some(col => col.name === 'litter_id');
|
return columns.some(col => col.name === 'litter_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if health_records has the old restrictive CHECK constraint on record_type
|
||||||
|
healthRecordsHasOldConstraint() {
|
||||||
|
try {
|
||||||
|
const row = this.db.prepare(
|
||||||
|
"SELECT sql FROM sqlite_master WHERE type='table' AND name='health_records'"
|
||||||
|
).get();
|
||||||
|
if (!row) return false;
|
||||||
|
// Old constraint lists only the 5 legacy types
|
||||||
|
return row.sql.includes("'test', 'vaccination', 'exam', 'treatment', 'certification'");
|
||||||
|
} catch (_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Migration 1: Remove sire/dam columns, use parents table
|
// Migration 1: Remove sire/dam columns, use parents table
|
||||||
migration001_removeOldParentColumns() {
|
migration001_removeOldParentColumns() {
|
||||||
console.log('[Migration 001] Checking for old sire/dam columns...');
|
console.log('[Migration 001] Checking for old sire/dam columns...');
|
||||||
@@ -204,6 +218,87 @@ class MigrationRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Migration 3: Remove old restrictive CHECK constraint on health_records.record_type
|
||||||
|
// The old schema only allowed: 'test','vaccination','exam','treatment','certification'
|
||||||
|
// The new schema allows any free-form text (ofa_clearance, etc.)
|
||||||
|
migration003_removeHealthRecordTypeConstraint() {
|
||||||
|
console.log('[Migration 003] Checking health_records.record_type constraint...');
|
||||||
|
|
||||||
|
if (!this.healthRecordsHasOldConstraint()) {
|
||||||
|
console.log('[Migration 003] No old constraint found, skipping');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[Migration 003] Rebuilding health_records table to remove old CHECK constraint...');
|
||||||
|
|
||||||
|
this.db.exec('BEGIN TRANSACTION');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Backup existing health records
|
||||||
|
this.db.exec('DROP TABLE IF EXISTS health_records_migration_backup');
|
||||||
|
this.db.exec('CREATE TABLE health_records_migration_backup AS SELECT * FROM health_records');
|
||||||
|
|
||||||
|
const backupCount = this.db.prepare('SELECT COUNT(*) as count FROM health_records_migration_backup').get();
|
||||||
|
console.log(`[Migration 003] Backed up ${backupCount.count} health records`);
|
||||||
|
|
||||||
|
// Drop old table (constraint is baked in and cannot be altered)
|
||||||
|
this.db.exec('DROP TABLE health_records');
|
||||||
|
|
||||||
|
// Recreate WITHOUT the old CHECK constraint on record_type
|
||||||
|
this.db.exec(`
|
||||||
|
CREATE TABLE health_records (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
dog_id INTEGER NOT NULL,
|
||||||
|
record_type TEXT NOT NULL,
|
||||||
|
test_type TEXT,
|
||||||
|
test_name TEXT,
|
||||||
|
test_date TEXT NOT NULL,
|
||||||
|
ofa_result TEXT,
|
||||||
|
ofa_number TEXT,
|
||||||
|
performed_by TEXT,
|
||||||
|
expires_at TEXT,
|
||||||
|
document_url TEXT,
|
||||||
|
result TEXT,
|
||||||
|
vet_name TEXT,
|
||||||
|
next_due TEXT,
|
||||||
|
notes TEXT,
|
||||||
|
created_at TEXT DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT DEFAULT (datetime('now')),
|
||||||
|
FOREIGN KEY (dog_id) REFERENCES dogs(id)
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Restore all existing records
|
||||||
|
this.db.exec(`
|
||||||
|
INSERT INTO health_records
|
||||||
|
(id, dog_id, record_type, test_type, test_name, test_date,
|
||||||
|
ofa_result, ofa_number, performed_by, expires_at,
|
||||||
|
document_url, result, vet_name, next_due, notes,
|
||||||
|
created_at, updated_at)
|
||||||
|
SELECT
|
||||||
|
id, dog_id, record_type, test_type, test_name, test_date,
|
||||||
|
ofa_result, ofa_number, performed_by, expires_at,
|
||||||
|
document_url, result, vet_name, next_due, notes,
|
||||||
|
created_at, updated_at
|
||||||
|
FROM health_records_migration_backup
|
||||||
|
`);
|
||||||
|
|
||||||
|
const restoredCount = this.db.prepare('SELECT COUNT(*) as count FROM health_records').get();
|
||||||
|
console.log(`[Migration 003] Restored ${restoredCount.count} health records`);
|
||||||
|
|
||||||
|
// Clean up backup
|
||||||
|
this.db.exec('DROP TABLE health_records_migration_backup');
|
||||||
|
|
||||||
|
this.db.exec('COMMIT');
|
||||||
|
console.log('[Migration 003] ✓ health_records constraint removed successfully!');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.db.exec('ROLLBACK');
|
||||||
|
console.error('[Migration 003] ✗ Migration failed:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Validate final schema
|
// Validate final schema
|
||||||
validateSchema() {
|
validateSchema() {
|
||||||
console.log('[Validation] Checking database schema...');
|
console.log('[Validation] Checking database schema...');
|
||||||
@@ -240,6 +335,10 @@ class MigrationRunner {
|
|||||||
const tables = this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='litters'").all();
|
const tables = this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='litters'").all();
|
||||||
return tables.length > 0;
|
return tables.length > 0;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'health_records has no old record_type CHECK constraint',
|
||||||
|
test: () => !this.healthRecordsHasOldConstraint()
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -284,6 +383,11 @@ class MigrationRunner {
|
|||||||
this.recordMigration(2, 'Add litter_id column to dogs table');
|
this.recordMigration(2, 'Add litter_id column to dogs table');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentVersion < 3) {
|
||||||
|
this.migration003_removeHealthRecordTypeConstraint();
|
||||||
|
this.recordMigration(3, 'Remove old record_type CHECK constraint from health_records');
|
||||||
|
}
|
||||||
|
|
||||||
// Validate final schema
|
// Validate final schema
|
||||||
console.log('');
|
console.log('');
|
||||||
const isValid = this.validateSchema();
|
const isValid = this.validateSchema();
|
||||||
|
|||||||
Reference in New Issue
Block a user