mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-07 09:51:37 +00:00
skip sqlite-only migrations on postgres
This commit is contained in:
parent
7d97d09191
commit
024f892902
10 changed files with 134 additions and 2 deletions
|
|
@ -19,8 +19,12 @@ async function up({ context: { queryInterface, logger } }) {
|
||||||
logger.info('[2.15.0 migration] UPGRADE BEGIN: 2.15.0-series-column-unique ')
|
logger.info('[2.15.0 migration] UPGRADE BEGIN: 2.15.0-series-column-unique ')
|
||||||
|
|
||||||
// Run reindex nocase to fix potential corruption issues due to the bad sqlite extension introduced in v2.12.0
|
// Run reindex nocase to fix potential corruption issues due to the bad sqlite extension introduced in v2.12.0
|
||||||
logger.info('[2.15.0 migration] Reindexing NOCASE indices to fix potential hidden corruption issues')
|
if (queryInterface.sequelize.getDialect() === 'sqlite') {
|
||||||
await queryInterface.sequelize.query('REINDEX NOCASE;')
|
logger.info('[2.15.0 migration] Reindexing NOCASE indices to fix potential hidden corruption issues')
|
||||||
|
await queryInterface.sequelize.query('REINDEX NOCASE;')
|
||||||
|
} else {
|
||||||
|
logger.info('[2.15.0 migration] Skipping NOCASE reindex on non-sqlite dialect')
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the unique index already exists
|
// Check if the unique index already exists
|
||||||
const seriesIndexes = await queryInterface.showIndex('Series')
|
const seriesIndexes = await queryInterface.showIndex('Series')
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,12 @@ async function up({ context: { queryInterface, logger } }) {
|
||||||
// Upwards migration script
|
// Upwards migration script
|
||||||
logger.info('[2.15.1 migration] UPGRADE BEGIN: 2.15.1-reindex-nocase ')
|
logger.info('[2.15.1 migration] UPGRADE BEGIN: 2.15.1-reindex-nocase ')
|
||||||
|
|
||||||
|
if (queryInterface.sequelize.getDialect() !== 'sqlite') {
|
||||||
|
logger.info('[2.15.1 migration] Skipping NOCASE reindex on non-sqlite dialect')
|
||||||
|
logger.info('[2.15.1 migration] UPGRADE END: 2.15.1-reindex-nocase ')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Run reindex nocase to fix potential corruption issues due to the bad sqlite extension introduced in v2.12.0
|
// Run reindex nocase to fix potential corruption issues due to the bad sqlite extension introduced in v2.12.0
|
||||||
logger.info('[2.15.1 migration] Reindexing NOCASE indices to fix potential hidden corruption issues')
|
logger.info('[2.15.1 migration] Reindexing NOCASE indices to fix potential hidden corruption issues')
|
||||||
await queryInterface.sequelize.query('REINDEX NOCASE;')
|
await queryInterface.sequelize.query('REINDEX NOCASE;')
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@ async function up({ context: { queryInterface, logger } }) {
|
||||||
// Upwards migration script
|
// Upwards migration script
|
||||||
logger.info('[2.17.3 migration] UPGRADE BEGIN: 2.17.3-fk-constraints')
|
logger.info('[2.17.3 migration] UPGRADE BEGIN: 2.17.3-fk-constraints')
|
||||||
|
|
||||||
|
if (queryInterface.sequelize.getDialect() !== 'sqlite') {
|
||||||
|
logger.info('[2.17.3 migration] Skipping sqlite-specific foreign key rewrite on non-sqlite dialect')
|
||||||
|
logger.info('[2.17.3 migration] UPGRADE END: 2.17.3-fk-constraints')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const execQuery = queryInterface.sequelize.query.bind(queryInterface.sequelize)
|
const execQuery = queryInterface.sequelize.query.bind(queryInterface.sequelize)
|
||||||
|
|
||||||
// Disable foreign key constraints for the next sequence of operations
|
// Disable foreign key constraints for the next sequence of operations
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,12 @@ async function up({ context: { queryInterface, logger } }) {
|
||||||
// Upwards migration script
|
// Upwards migration script
|
||||||
logger.info(`${loggerPrefix} UPGRADE BEGIN: ${migrationName}`)
|
logger.info(`${loggerPrefix} UPGRADE BEGIN: ${migrationName}`)
|
||||||
|
|
||||||
|
if (queryInterface.sequelize.getDialect() !== 'sqlite') {
|
||||||
|
logger.info(`${loggerPrefix} skipping sqlite-specific migration on non-sqlite dialect`)
|
||||||
|
logger.info(`${loggerPrefix} UPGRADE END: ${migrationName}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
await addColumn(queryInterface, logger, 'libraryItems', 'title', { type: queryInterface.sequelize.Sequelize.STRING, allowNull: true })
|
await addColumn(queryInterface, logger, 'libraryItems', 'title', { type: queryInterface.sequelize.Sequelize.STRING, allowNull: true })
|
||||||
await copyColumn(queryInterface, logger, 'books', 'title', 'id', 'libraryItems', 'title', 'mediaId')
|
await copyColumn(queryInterface, logger, 'books', 'title', 'id', 'libraryItems', 'title', 'mediaId')
|
||||||
await addTrigger(queryInterface, logger, 'books', 'title', 'id', 'libraryItems', 'title', 'mediaId')
|
await addTrigger(queryInterface, logger, 'books', 'title', 'id', 'libraryItems', 'title', 'mediaId')
|
||||||
|
|
@ -51,6 +57,12 @@ async function down({ context: { queryInterface, logger } }) {
|
||||||
// Downward migration script
|
// Downward migration script
|
||||||
logger.info(`${loggerPrefix} DOWNGRADE BEGIN: ${migrationName}`)
|
logger.info(`${loggerPrefix} DOWNGRADE BEGIN: ${migrationName}`)
|
||||||
|
|
||||||
|
if (queryInterface.sequelize.getDialect() !== 'sqlite') {
|
||||||
|
logger.info(`${loggerPrefix} skipping sqlite-specific rollback on non-sqlite dialect`)
|
||||||
|
logger.info(`${loggerPrefix} DOWNGRADE END: ${migrationName}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
await removeIndex(queryInterface, logger, 'libraryItems', ['libraryId', 'mediaType', 'title'])
|
await removeIndex(queryInterface, logger, 'libraryItems', ['libraryId', 'mediaType', 'title'])
|
||||||
await removeTrigger(queryInterface, logger, 'libraryItems', 'title')
|
await removeTrigger(queryInterface, logger, 'libraryItems', 'title')
|
||||||
await removeColumn(queryInterface, logger, 'libraryItems', 'title')
|
await removeColumn(queryInterface, logger, 'libraryItems', 'title')
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,12 @@ async function up({ context: { queryInterface, logger } }) {
|
||||||
// Upwards migration script
|
// Upwards migration script
|
||||||
logger.info(`${loggerPrefix} UPGRADE BEGIN: ${migrationName}`)
|
logger.info(`${loggerPrefix} UPGRADE BEGIN: ${migrationName}`)
|
||||||
|
|
||||||
|
if (queryInterface.sequelize.getDialect() !== 'sqlite') {
|
||||||
|
logger.info(`${loggerPrefix} skipping sqlite-specific migration on non-sqlite dialect`)
|
||||||
|
logger.info(`${loggerPrefix} UPGRADE END: ${migrationName}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Add numEpisodes column to podcasts table
|
// Add numEpisodes column to podcasts table
|
||||||
await addColumn(queryInterface, logger, 'podcasts', 'numEpisodes', { type: queryInterface.sequelize.Sequelize.INTEGER, allowNull: false, defaultValue: 0 })
|
await addColumn(queryInterface, logger, 'podcasts', 'numEpisodes', { type: queryInterface.sequelize.Sequelize.INTEGER, allowNull: false, defaultValue: 0 })
|
||||||
|
|
||||||
|
|
@ -60,6 +66,12 @@ async function down({ context: { queryInterface, logger } }) {
|
||||||
// Downward migration script
|
// Downward migration script
|
||||||
logger.info(`${loggerPrefix} DOWNGRADE BEGIN: ${migrationName}`)
|
logger.info(`${loggerPrefix} DOWNGRADE BEGIN: ${migrationName}`)
|
||||||
|
|
||||||
|
if (queryInterface.sequelize.getDialect() !== 'sqlite') {
|
||||||
|
logger.info(`${loggerPrefix} skipping sqlite-specific rollback on non-sqlite dialect`)
|
||||||
|
logger.info(`${loggerPrefix} DOWNGRADE END: ${migrationName}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Remove triggers from libraryItems
|
// Remove triggers from libraryItems
|
||||||
await removeTrigger(queryInterface, logger, 'podcasts', 'title', 'libraryItems', 'title')
|
await removeTrigger(queryInterface, logger, 'podcasts', 'title', 'libraryItems', 'title')
|
||||||
await removeTrigger(queryInterface, logger, 'podcasts', 'titleIgnorePrefix', 'libraryItems', 'titleIgnorePrefix')
|
await removeTrigger(queryInterface, logger, 'podcasts', 'titleIgnorePrefix', 'libraryItems', 'titleIgnorePrefix')
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,23 @@ describe('migration-v2.15.0-series-column-unique', () => {
|
||||||
await queryInterface.dropTable('Series')
|
await queryInterface.dropTable('Series')
|
||||||
await queryInterface.dropTable('BookSeries')
|
await queryInterface.dropTable('BookSeries')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should skip NOCASE reindex on postgres dialect', async () => {
|
||||||
|
sinon.stub(queryInterface.sequelize, 'getDialect').returns('postgres')
|
||||||
|
const originalQuery = queryInterface.sequelize.query.bind(queryInterface.sequelize)
|
||||||
|
const queryStub = sinon.stub(queryInterface.sequelize, 'query').callsFake((sql, options) => {
|
||||||
|
if (sql === 'REINDEX NOCASE;') {
|
||||||
|
throw new Error('Unexpected NOCASE reindex in postgres mode')
|
||||||
|
}
|
||||||
|
return originalQuery(sql, options)
|
||||||
|
})
|
||||||
|
|
||||||
|
await up({ context: { queryInterface, logger: Logger } })
|
||||||
|
|
||||||
|
expect(queryStub.neverCalledWith('REINDEX NOCASE;')).to.be.true
|
||||||
|
expect(loggerInfoStub.calledWith(sinon.match('[2.15.0 migration] Skipping NOCASE reindex on non-sqlite dialect'))).to.be.true
|
||||||
|
})
|
||||||
|
|
||||||
it('upgrade with no duplicate series', async () => {
|
it('upgrade with no duplicate series', async () => {
|
||||||
// Add some entries to the Series table using the UUID for the ids
|
// Add some entries to the Series table using the UUID for the ids
|
||||||
await queryInterface.bulkInsert('Series', [
|
await queryInterface.bulkInsert('Series', [
|
||||||
|
|
|
||||||
41
test/server/migrations/v2.15.1-reindex-nocase.test.js
Normal file
41
test/server/migrations/v2.15.1-reindex-nocase.test.js
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
const { expect } = require('chai')
|
||||||
|
const sinon = require('sinon')
|
||||||
|
|
||||||
|
const { up, down } = require('../../../server/migrations/v2.15.1-reindex-nocase')
|
||||||
|
const Logger = require('../../../server/Logger')
|
||||||
|
|
||||||
|
describe('migration-v2.15.1-reindex-nocase', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
sinon.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should skip reindex on non-sqlite dialect', async () => {
|
||||||
|
const queryStub = sinon.stub().resolves()
|
||||||
|
const loggerInfoStub = sinon.stub(Logger, 'info')
|
||||||
|
const queryInterface = {
|
||||||
|
sequelize: {
|
||||||
|
getDialect: () => 'postgres',
|
||||||
|
query: queryStub
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await up({ context: { queryInterface, logger: Logger } })
|
||||||
|
|
||||||
|
expect(queryStub.called).to.equal(false)
|
||||||
|
expect(loggerInfoStub.calledWith(sinon.match('[2.15.1 migration] Skipping NOCASE reindex on non-sqlite dialect'))).to.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should log no-op on down migration', async () => {
|
||||||
|
const loggerInfoStub = sinon.stub(Logger, 'info')
|
||||||
|
const queryInterface = {
|
||||||
|
sequelize: {
|
||||||
|
getDialect: () => 'postgres',
|
||||||
|
query: sinon.stub().resolves()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await down({ context: { queryInterface, logger: Logger } })
|
||||||
|
|
||||||
|
expect(loggerInfoStub.calledWith(sinon.match('[2.15.1 migration] No action required for downgrade'))).to.equal(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -34,6 +34,16 @@ describe('migration-v2.17.3-fk-constraints', () => {
|
||||||
await queryInterface.dropAllTables()
|
await queryInterface.dropAllTables()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should skip sqlite-specific migration on non-sqlite dialect', async () => {
|
||||||
|
sinon.stub(queryInterface.sequelize, 'getDialect').returns('postgres')
|
||||||
|
const queryStub = sinon.stub(queryInterface.sequelize, 'query').resolves([])
|
||||||
|
|
||||||
|
await up({ context: { queryInterface, logger: Logger } })
|
||||||
|
|
||||||
|
expect(queryStub.called).to.equal(false)
|
||||||
|
expect(loggerInfoStub.calledWith(sinon.match('[2.17.3 migration] Skipping sqlite-specific foreign key rewrite on non-sqlite dialect'))).to.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
it('should fix table foreign key constraints', async () => {
|
it('should fix table foreign key constraints', async () => {
|
||||||
// Create tables with missing foreign key constraints: libraryItems, feeds, mediaItemShares, playbackSessions, playlistMediaItems, mediaProgresses
|
// Create tables with missing foreign key constraints: libraryItems, feeds, mediaItemShares, playbackSessions, playlistMediaItems, mediaProgresses
|
||||||
await queryInterface.sequelize.query('CREATE TABLE `libraryItems` (`id` UUID UNIQUE PRIMARY KEY, `libraryId` UUID REFERENCES `libraries` (`id`), `libraryFolderId` UUID REFERENCES `libraryFolders` (`id`));')
|
await queryInterface.sequelize.query('CREATE TABLE `libraryItems` (`id` UUID UNIQUE PRIMARY KEY, `libraryId` UUID REFERENCES `libraries` (`id`), `libraryFolderId` UUID REFERENCES `libraryFolders` (`id`));')
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,18 @@ describe('Migration v2.19.1-copy-title-to-library-items', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('up', () => {
|
describe('up', () => {
|
||||||
|
it('should skip sqlite-specific migration on non-sqlite dialect', async () => {
|
||||||
|
sinon.stub(queryInterface.sequelize, 'getDialect').returns('postgres')
|
||||||
|
|
||||||
|
await up({ context: { queryInterface, logger: Logger } })
|
||||||
|
|
||||||
|
const table = await queryInterface.describeTable('libraryItems')
|
||||||
|
expect(table).to.have.property('id')
|
||||||
|
expect(table).to.not.have.property('title')
|
||||||
|
expect(table).to.not.have.property('titleIgnorePrefix')
|
||||||
|
expect(loggerInfoStub.calledWith(sinon.match('[2.19.1 migration] skipping sqlite-specific migration on non-sqlite dialect'))).to.be.true
|
||||||
|
})
|
||||||
|
|
||||||
it('should copy title and titleIgnorePrefix to libraryItems', async () => {
|
it('should copy title and titleIgnorePrefix to libraryItems', async () => {
|
||||||
await up({ context: { queryInterface, logger: Logger } })
|
await up({ context: { queryInterface, logger: Logger } })
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,18 @@ describe('Migration v2.19.4-improve-podcast-queries', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('up', () => {
|
describe('up', () => {
|
||||||
|
it('should skip sqlite-specific migration on non-sqlite dialect', async () => {
|
||||||
|
sinon.stub(queryInterface.sequelize, 'getDialect').returns('postgres')
|
||||||
|
|
||||||
|
await up({ context: { queryInterface, logger: Logger } })
|
||||||
|
|
||||||
|
const podcastsTable = await queryInterface.describeTable('podcasts')
|
||||||
|
const mediaProgressesTable = await queryInterface.describeTable('mediaProgresses')
|
||||||
|
expect(podcastsTable).to.not.have.property('numEpisodes')
|
||||||
|
expect(mediaProgressesTable).to.not.have.property('podcastId')
|
||||||
|
expect(loggerInfoStub.calledWith(sinon.match('[2.19.4 migration] skipping sqlite-specific migration on non-sqlite dialect'))).to.be.true
|
||||||
|
})
|
||||||
|
|
||||||
it('should add numEpisodes column to podcasts', async () => {
|
it('should add numEpisodes column to podcasts', async () => {
|
||||||
await up({ context: { queryInterface, logger: Logger } })
|
await up({ context: { queryInterface, logger: Logger } })
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue