2018-04-01 21:27:46 -04:00
const backupService = require ( './backup' ) ;
2017-10-22 20:22:09 -04:00
const sql = require ( './sql' ) ;
const fs = require ( 'fs-extra' ) ;
2017-10-24 22:17:48 -04:00
const log = require ( './log' ) ;
2018-11-18 09:05:50 +01:00
const utils = require ( './utils' ) ;
2018-04-01 21:27:46 -04:00
const resourceDir = require ( './resource_dir' ) ;
2020-07-02 22:57:17 +02:00
const appInfo = require ( './app_info' ) ;
2017-10-22 20:22:09 -04:00
2020-07-02 22:57:17 +02:00
async function migrate ( ) {
2021-09-23 22:08:23 +02:00
const currentDbVersion = getDbVersion ( ) ;
if ( currentDbVersion < 183 ) {
log . error ( "Direct migration from your current version is not supported. Please upgrade to the latest v0.47.X first and only then to this version." ) ;
utils . crash ( ) ;
return ;
}
2017-10-22 20:22:09 -04:00
2023-05-07 15:46:17 +02:00
// backup before attempting migration
await backupService . backupNow (
// special name for the pre-0.60 migration to prevent later overwrite
currentDbVersion < 214
? ` before-migration-v ${ currentDbVersion } `
: 'before-migration'
) ;
const migrations = fs . readdirSync ( resourceDir . MIGRATIONS _DIR ) . map ( file => {
2022-12-27 21:17:40 +01:00
const match = file . match ( /^([0-9]{4})__([a-zA-Z0-9_ ]+)\.(sql|js)$/ ) ;
2023-05-07 15:46:17 +02:00
if ( ! match ) {
return null ;
}
2017-10-22 20:22:09 -04:00
2023-05-07 15:46:17 +02:00
const dbVersion = parseInt ( match [ 1 ] ) ;
if ( dbVersion > currentDbVersion ) {
const name = match [ 2 ] ;
const type = match [ 3 ] ;
return {
dbVersion : dbVersion ,
name : name ,
file : file ,
type : type
} ;
} else {
return null ;
2017-10-22 20:22:09 -04:00
}
2023-05-07 15:46:17 +02:00
} ) . filter ( el => ! ! el ) ;
2017-10-22 20:22:09 -04:00
2017-11-05 18:59:58 -05:00
migrations . sort ( ( a , b ) => a . dbVersion - b . dbVersion ) ;
2017-10-22 20:22:09 -04:00
2023-05-05 23:41:11 +02:00
// all migrations are executed in one transaction - upgrade either succeeds, or the user can stay at the old version
2022-12-22 19:02:41 +01:00
// otherwise if half of the migrations succeed, user can't use any version - DB is too "new" for the old app,
// and too old for the new app version.
2022-12-22 18:53:04 +01:00
sql . transactional ( ( ) => {
for ( const mig of migrations ) {
try {
log . info ( ` Attempting migration to version ${ mig . dbVersion } ` ) ;
2017-10-22 20:22:09 -04:00
2022-12-22 18:53:04 +01:00
executeMigration ( mig ) ;
2017-10-22 20:22:09 -04:00
2022-12-22 18:53:04 +01:00
sql . execute ( ` UPDATE options
SET value = ?
WHERE name = ? ` , [mig.dbVersion.toString(), "dbVersion"]);
2021-01-30 22:17:29 +01:00
2022-12-22 18:53:04 +01:00
log . info ( ` Migration to version ${ mig . dbVersion } has been successful. ` ) ;
} catch ( e ) {
log . error ( ` error during migration to version ${ mig . dbVersion } : ${ e . stack } ` ) ;
2022-12-27 14:52:32 +01:00
log . error ( "migration failed, crashing hard" ) ; // this is not very user-friendly :-/
2017-10-22 20:22:09 -04:00
2022-12-22 18:53:04 +01:00
utils . crash ( ) ;
2022-12-27 14:52:32 +01:00
break ; // crash() above does not seem to work right away
2022-12-22 18:53:04 +01:00
}
2017-10-22 20:22:09 -04:00
}
2022-12-22 18:53:04 +01:00
} ) ;
}
function executeMigration ( mig ) {
if ( mig . type === 'sql' ) {
const migrationSql = fs . readFileSync ( ` ${ resourceDir . MIGRATIONS _DIR } / ${ mig . file } ` ) . toString ( 'utf8' ) ;
console . log ( ` Migration with SQL script: ${ migrationSql } ` ) ;
sql . executeScript ( migrationSql ) ;
} else if ( mig . type === 'js' ) {
console . log ( "Migration with JS module" ) ;
const migrationModule = require ( ` ${ resourceDir . MIGRATIONS _DIR } / ${ mig . file } ` ) ;
migrationModule ( ) ;
} else {
2023-06-29 22:10:13 +02:00
throw new Error ( ` Unknown migration type ' ${ mig . type } ' ` ) ;
2017-10-22 20:22:09 -04:00
}
2020-07-02 22:57:17 +02:00
}
function getDbVersion ( ) {
return parseInt ( sql . getValue ( "SELECT value FROM options WHERE name = 'dbVersion'" ) ) ;
}
function isDbUpToDate ( ) {
const dbVersion = getDbVersion ( ) ;
const upToDate = dbVersion >= appInfo . dbVersion ;
if ( ! upToDate ) {
2022-12-21 15:19:05 +01:00
log . info ( ` App db version is ${ appInfo . dbVersion } , while db version is ${ dbVersion } . Migration needed. ` ) ;
2020-07-02 22:57:17 +02:00
}
return upToDate ;
}
2017-10-24 22:17:48 -04:00
2020-07-02 22:57:17 +02:00
async function migrateIfNecessary ( ) {
const currentDbVersion = getDbVersion ( ) ;
2022-06-06 22:27:06 +02:00
if ( currentDbVersion > appInfo . dbVersion && process . env . TRILIUM _IGNORE _DB _VERSION !== 'true' ) {
2023-06-29 22:10:13 +02:00
log . error ( ` Current DB version ${ currentDbVersion } is newer than the current DB version ${ appInfo . dbVersion } , which means that it was created by a newer and incompatible version of Trilium. Upgrade to the latest version of Trilium to resolve this issue. ` ) ;
2020-07-02 22:57:17 +02:00
utils . crash ( ) ;
}
2020-06-23 13:38:27 +02:00
2020-07-02 22:57:17 +02:00
if ( ! isDbUpToDate ( ) ) {
await migrate ( ) ;
2017-12-12 23:35:41 -05:00
}
2017-10-22 20:22:09 -04:00
}
module . exports = {
2023-01-16 08:06:19 +01:00
migrateIfNecessary ,
isDbUpToDate
2020-06-20 12:31:38 +02:00
} ;