fix: Improve Migration Error Handling

This commit is contained in:
Rajarshee Chatterjee
2025-11-16 13:18:58 +05:30
parent 4c0e7f6013
commit 3af24f0815
3 changed files with 125 additions and 89 deletions
+19 -5
View File
@@ -31,7 +31,7 @@ export const db = SQLite.openDatabaseSync(dbName);
/**
* Creates the initial database schema for fresh installations
* Sets up all tables, indexes, triggers and sets version to 1
* Sets up all tables, indexes, triggers and sets version to 2
*/
const createInitialSchema = () => {
db.execSync('PRAGMA journal_mode = WAL');
@@ -52,7 +52,7 @@ const createInitialSchema = () => {
db.runSync(createNovelTriggerQueryUpdate);
db.runSync(createNovelTriggerQueryDelete);
db.execSync('PRAGMA user_version = 1');
db.execSync('PRAGMA user_version = 2');
});
};
@@ -65,9 +65,23 @@ export const initializeDatabase = () => {
db.execSync('PRAGMA cache_size = 10000');
db.execSync('PRAGMA foreign_keys = ON');
const userVersion =
db.getFirstSync<{ user_version: number }>('PRAGMA user_version')
?.user_version ?? 0;
let userVersion = 0;
try {
const result = db.getFirstSync<{ user_version: number }>(
'PRAGMA user_version',
);
userVersion = result?.user_version ?? 0;
} catch (error) {
// If PRAGMA query fails, assume fresh database
if (__DEV__) {
// eslint-disable-next-line no-console
console.warn(
'Failed to get database version, assuming fresh install:',
error,
);
}
userVersion = 0;
}
if (userVersion === 0) {
createInitialSchema();
@@ -27,86 +27,99 @@ export const migration002: Migration = {
version: 2,
description: 'Add counter columns and triggers to Novel table',
migrate: db => {
if (!columnExists(db, 'Novel', 'chaptersDownloaded')) {
db.runSync(`
ALTER TABLE Novel
ADD COLUMN chaptersDownloaded INTEGER DEFAULT 0
`);
const addColumnSafely = (columnName: string, columnDefinition: string) => {
if (!columnExists(db, 'Novel', columnName)) {
try {
db.runSync(`
ALTER TABLE Novel
ADD COLUMN ${columnName} ${columnDefinition}
`);
} catch (error) {
// Gracefully handle ALTER TABLE failures (e.g., table doesn't exist)
// Columns will be created when table is created in initial schema
if (__DEV__) {
// eslint-disable-next-line no-console
console.warn(
`Failed to add column ${columnName} to Novel table:`,
error,
);
}
}
}
};
addColumnSafely('chaptersDownloaded', 'INTEGER DEFAULT 0');
addColumnSafely('chaptersUnread', 'INTEGER DEFAULT 0');
addColumnSafely('totalChapters', 'INTEGER DEFAULT 0');
addColumnSafely('lastReadAt', 'TEXT');
addColumnSafely('lastUpdatedAt', 'TEXT');
// Verify all columns exist before running UPDATE queries to prevent SQL errors
const allColumnsExist =
columnExists(db, 'Novel', 'chaptersDownloaded') &&
columnExists(db, 'Novel', 'chaptersUnread') &&
columnExists(db, 'Novel', 'totalChapters') &&
columnExists(db, 'Novel', 'lastReadAt') &&
columnExists(db, 'Novel', 'lastUpdatedAt');
if (allColumnsExist) {
try {
db.runSync(`
UPDATE Novel
SET chaptersDownloaded = (
SELECT COUNT(*)
FROM Chapter
WHERE Chapter.novelId = Novel.id
AND Chapter.isDownloaded = 1
)
`);
db.runSync(`
UPDATE Novel
SET chaptersUnread = (
SELECT COUNT(*)
FROM Chapter
WHERE Chapter.novelId = Novel.id
AND Chapter.unread = 1
)
`);
db.runSync(`
UPDATE Novel
SET totalChapters = (
SELECT COUNT(*)
FROM Chapter
WHERE Chapter.novelId = Novel.id
)
`);
db.runSync(`
UPDATE Novel
SET lastReadAt = (
SELECT MAX(readTime)
FROM Chapter
WHERE Chapter.novelId = Novel.id
)
`);
db.runSync(`
UPDATE Novel
SET lastUpdatedAt = (
SELECT MAX(updatedTime)
FROM Chapter
WHERE Chapter.novelId = Novel.id
)
`);
} catch (error) {
// Gracefully handle UPDATE failures - columns already added with defaults
if (__DEV__) {
// eslint-disable-next-line no-console
console.warn(
'Failed to populate counter columns in Novel table:',
error,
);
}
}
}
if (!columnExists(db, 'Novel', 'chaptersUnread')) {
db.runSync(`
ALTER TABLE Novel
ADD COLUMN chaptersUnread INTEGER DEFAULT 0
`);
}
if (!columnExists(db, 'Novel', 'totalChapters')) {
db.runSync(`
ALTER TABLE Novel
ADD COLUMN totalChapters INTEGER DEFAULT 0
`);
}
if (!columnExists(db, 'Novel', 'lastReadAt')) {
db.runSync(`
ALTER TABLE Novel
ADD COLUMN lastReadAt TEXT
`);
}
if (!columnExists(db, 'Novel', 'lastUpdatedAt')) {
db.runSync(`
ALTER TABLE Novel
ADD COLUMN lastUpdatedAt TEXT
`);
}
db.runSync(`
UPDATE Novel
SET chaptersDownloaded = (
SELECT COUNT(*)
FROM Chapter
WHERE Chapter.novelId = Novel.id
AND Chapter.isDownloaded = 1
)
`);
db.runSync(`
UPDATE Novel
SET chaptersUnread = (
SELECT COUNT(*)
FROM Chapter
WHERE Chapter.novelId = Novel.id
AND Chapter.unread = 1
)
`);
db.runSync(`
UPDATE Novel
SET totalChapters = (
SELECT COUNT(*)
FROM Chapter
WHERE Chapter.novelId = Novel.id
)
`);
db.runSync(`
UPDATE Novel
SET lastReadAt = (
SELECT MAX(readTime)
FROM Chapter
WHERE Chapter.novelId = Novel.id
)
`);
db.runSync(`
UPDATE Novel
SET lastUpdatedAt = (
SELECT MAX(updatedTime)
FROM Chapter
WHERE Chapter.novelId = Novel.id
)
`);
},
};
+13 -4
View File
@@ -49,10 +49,19 @@ export class MigrationRunner {
}
private getCurrentVersion(db: SQLiteDatabase): number {
return (
db.getFirstSync<{ user_version: number }>('PRAGMA user_version')
?.user_version ?? 0
);
try {
const result = db.getFirstSync<{ user_version: number }>(
'PRAGMA user_version',
);
return result?.user_version ?? 0;
} catch (error) {
// If PRAGMA query fails, assume version 0 (fresh database)
if (__DEV__) {
// eslint-disable-next-line no-console
console.warn('Failed to get database version, assuming 0:', error);
}
return 0;
}
}
private setVersion(db: SQLiteDatabase, version: number): void {