fix: fix database migration errors

fix the H2 database before attempting a migration. This solves the following errors:
- [SQLITE_CONSTRAINT_PRIMARYKEY]  A PRIMARY KEY constraint failed (UNIQUE constraint failed: READ_PROGRESS.BOOK_ID, READ_PROGRESS.USER_ID)
- [SQLITE_CONSTRAINT_NOTNULL] A NOT NULL constraint failed (NOT NULL constraint failed: MEDIA_PAGE.NUMBER)

closes #239, closes #238, closes #237, closes #240
This commit is contained in:
Gauthier Roebroeck 2020-07-21 15:36:27 +08:00
parent 1c28a9496b
commit f84ba17079

View File

@ -100,6 +100,8 @@ class DatabaseMigration(
logger.info { "Stopping all JMS listeners" }
jmsListenerEndpointRegistry.stop()
fixH2Database()
var rows: Int
measureTime {
rows = transferH2DataToSqlite()
@ -159,6 +161,44 @@ class DatabaseMigration(
logger.info { "Backup finished" }
}
private fun fixH2Database() {
logger.info { "Checking H2 database for inconsistent data" }
val jdbc = JdbcTemplate(h2DataSource)
val countBook = jdbc.queryForObject("select count(distinct BOOK_ID) from media_page where number is null", Integer::class.java)!!
if (countBook > 0) {
logger.info { "Found $countBook books with missing page numbers, marking them as to be re-analyzed" }
jdbc.update("""
update media set STATUS='UNKNOWN'
where BOOK_ID in (
select distinct BOOK_ID from media_page where number is null
)""")
jdbc.update("delete from media_page where number is null")
jdbc.update("""
delete from media_page
where BOOK_ID in (
select distinct BOOK_ID from media_page where number is null
)""")
}
val invalidReadProgress = jdbc.query("""
select b.id as BOOK_ID, u.id as USER_ID, count(p.BOOK_ID)
from read_progress p left join user u on p.user_id = u.id left join book b on p.book_id = b.id
group by b.id, b.name, u.id, u.email
having count(p.book_id) > 1
""") { rs, _ -> Triple(rs.getLong(1), rs.getLong(2), rs.getLong(3)) }
if (invalidReadProgress.isNotEmpty()) {
logger.info { "Found ${invalidReadProgress.size} invalid read progress, removing extra rows and keep one per (book,user)" }
invalidReadProgress.forEach {
jdbc.update("delete from read_progress where book_id = ? and user_id = ? and rownum() < ?",
it.first, it.second, it.third
)
}
}
}
private fun transferH2DataToSqlite(): Int {
val maxBatchSize = komgaProperties.database.batchSize