diff --git a/server/migrations/v2.15.0-series-column-unique.js b/server/migrations/v2.15.0-series-column-unique.js index 7f8526f97..be782225a 100644 --- a/server/migrations/v2.15.0-series-column-unique.js +++ b/server/migrations/v2.15.0-series-column-unique.js @@ -19,8 +19,12 @@ async function up({ context: { queryInterface, logger } }) { 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 - logger.info('[2.15.0 migration] Reindexing NOCASE indices to fix potential hidden corruption issues') - await queryInterface.sequelize.query('REINDEX NOCASE;') + if (queryInterface.sequelize.getDialect() === 'sqlite') { + 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 const seriesIndexes = await queryInterface.showIndex('Series') diff --git a/server/migrations/v2.15.1-reindex-nocase.js b/server/migrations/v2.15.1-reindex-nocase.js index 2ec9487d2..429edf9ff 100644 --- a/server/migrations/v2.15.1-reindex-nocase.js +++ b/server/migrations/v2.15.1-reindex-nocase.js @@ -17,6 +17,12 @@ async function up({ context: { queryInterface, logger } }) { // Upwards migration script 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 logger.info('[2.15.1 migration] Reindexing NOCASE indices to fix potential hidden corruption issues') await queryInterface.sequelize.query('REINDEX NOCASE;') diff --git a/server/migrations/v2.17.3-fk-constraints.js b/server/migrations/v2.17.3-fk-constraints.js index 5f8a5c9a6..3ad61e585 100644 --- a/server/migrations/v2.17.3-fk-constraints.js +++ b/server/migrations/v2.17.3-fk-constraints.js @@ -18,6 +18,12 @@ async function up({ context: { queryInterface, logger } }) { // Upwards migration script 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) // Disable foreign key constraints for the next sequence of operations diff --git a/server/migrations/v2.19.1-copy-title-to-library-items.js b/server/migrations/v2.19.1-copy-title-to-library-items.js index 7b75fa855..d62b008ed 100644 --- a/server/migrations/v2.19.1-copy-title-to-library-items.js +++ b/server/migrations/v2.19.1-copy-title-to-library-items.js @@ -25,6 +25,12 @@ async function up({ context: { queryInterface, logger } }) { // Upwards migration script 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 copyColumn(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 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 removeTrigger(queryInterface, logger, 'libraryItems', 'title') await removeColumn(queryInterface, logger, 'libraryItems', 'title') diff --git a/server/migrations/v2.19.4-improve-podcast-queries.js b/server/migrations/v2.19.4-improve-podcast-queries.js index 689795c31..3becd3162 100644 --- a/server/migrations/v2.19.4-improve-podcast-queries.js +++ b/server/migrations/v2.19.4-improve-podcast-queries.js @@ -26,6 +26,12 @@ async function up({ context: { queryInterface, logger } }) { // Upwards migration script 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 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 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 await removeTrigger(queryInterface, logger, 'podcasts', 'title', 'libraryItems', 'title') await removeTrigger(queryInterface, logger, 'podcasts', 'titleIgnorePrefix', 'libraryItems', 'titleIgnorePrefix') diff --git a/test/server/migrations/v2.15.0-series-column-unique.test.js b/test/server/migrations/v2.15.0-series-column-unique.test.js index 7fce7b7a1..0439dbbb5 100644 --- a/test/server/migrations/v2.15.0-series-column-unique.test.js +++ b/test/server/migrations/v2.15.0-series-column-unique.test.js @@ -88,6 +88,23 @@ describe('migration-v2.15.0-series-column-unique', () => { await queryInterface.dropTable('Series') 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 () => { // Add some entries to the Series table using the UUID for the ids await queryInterface.bulkInsert('Series', [ diff --git a/test/server/migrations/v2.15.1-reindex-nocase.test.js b/test/server/migrations/v2.15.1-reindex-nocase.test.js new file mode 100644 index 000000000..50fe89174 --- /dev/null +++ b/test/server/migrations/v2.15.1-reindex-nocase.test.js @@ -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) + }) +}) diff --git a/test/server/migrations/v2.17.3-fk-constraints.test.js b/test/server/migrations/v2.17.3-fk-constraints.test.js index 33be43ce8..975302831 100644 --- a/test/server/migrations/v2.17.3-fk-constraints.test.js +++ b/test/server/migrations/v2.17.3-fk-constraints.test.js @@ -34,6 +34,16 @@ describe('migration-v2.17.3-fk-constraints', () => { 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 () => { // 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`));') diff --git a/test/server/migrations/v2.19.1-copy-title-to-library-items.test.js b/test/server/migrations/v2.19.1-copy-title-to-library-items.test.js index 5b7678567..7e291927d 100644 --- a/test/server/migrations/v2.19.1-copy-title-to-library-items.test.js +++ b/test/server/migrations/v2.19.1-copy-title-to-library-items.test.js @@ -47,6 +47,18 @@ describe('Migration v2.19.1-copy-title-to-library-items', () => { }) 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 () => { await up({ context: { queryInterface, logger: Logger } }) diff --git a/test/server/migrations/v2.19.4-improve-podcast-queries.test.js b/test/server/migrations/v2.19.4-improve-podcast-queries.test.js index 0ca697d70..e385318ad 100644 --- a/test/server/migrations/v2.19.4-improve-podcast-queries.test.js +++ b/test/server/migrations/v2.19.4-improve-podcast-queries.test.js @@ -75,6 +75,18 @@ describe('Migration v2.19.4-improve-podcast-queries', () => { }) 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 () => { await up({ context: { queryInterface, logger: Logger } })