diff --git a/src/database/schemamanager.cpp b/src/database/schemamanager.cpp index 1e2e2122d7bb..f59103f06a5c 100644 --- a/src/database/schemamanager.cpp +++ b/src/database/schemamanager.cpp @@ -189,6 +189,24 @@ SchemaManager::Result SchemaManager::upgradeToSchemaVersion( } FwdSqlQuery query(m_database, statement); result = query.isPrepared() && query.execPrepared(); + if (!result && + query.hasError() && + query.lastError().databaseText().startsWith( + QStringLiteral("duplicate column name: "))) { + // New columns may have already been added during a previous + // migration to a different (= preceding) schema version. This + // is a very common situation during development when switching + // between schema versions. Since SQLite does not allow to add + // new columns only if they do not yet exist we need to account + // for and handle those errors here after they occurred. If the + // remaining migration finishes without other errors this is + // probably ok. + kLogger.warning() + << "Ignoring failed statement" + << statement + << "and continuing with schema migration"; + result = true; + } } if (result) { diff --git a/src/test/schemamanager_test.cpp b/src/test/schemamanager_test.cpp index 12a994764e6e..3c48e7775687 100644 --- a/src/test/schemamanager_test.cpp +++ b/src/test/schemamanager_test.cpp @@ -104,7 +104,28 @@ TEST_F(SchemaManagerTest, BackwardsIncompatibleVersion) { EXPECT_EQ(SchemaManager::Result::NewerVersionIncompatible, result); } -TEST_F(SchemaManagerTest, FailedUpgrade) { +TEST_F(SchemaManagerTest, IgnoreDuplicateColumn) { + // Establish preconditions for test + { + // Upgrade to version 3 to get the modern library table. + SchemaManager schemaManager(dbConnection()); + SchemaManager::Result result = schemaManager.upgradeToSchemaVersion( + MixxxDb::kDefaultSchemaFile, 3); + ASSERT_EQ(SchemaManager::Result::UpgradeSucceeded, result); + } + + // Add a column that will be added again in version 24. + QSqlQuery query(dbConnection()); + ASSERT_TRUE(query.exec( + "ALTER TABLE library ADD COLUMN coverart_source TEXT")); + + SchemaManager schemaManager(dbConnection()); + SchemaManager::Result result = schemaManager.upgradeToSchemaVersion( + MixxxDb::kDefaultSchemaFile, MixxxDb::kRequiredSchemaVersion); + EXPECT_EQ(SchemaManager::Result::UpgradeSucceeded, result); +} + +TEST_F(SchemaManagerTest, UpgradeFailed) { // Establish preconditions for test { // Upgrade to version 3 to get the modern library table. @@ -114,10 +135,10 @@ TEST_F(SchemaManagerTest, FailedUpgrade) { EXPECT_EQ(SchemaManager::Result::UpgradeSucceeded, result); } - // Add a column that is added in version 24. + // Drop a table that is expected to exist. QSqlQuery query(dbConnection()); EXPECT_TRUE(query.exec( - "ALTER TABLE library ADD COLUMN coverart_source TEXT")); + "DROP TABLE PlaylistTracks")); SchemaManager schemaManager(dbConnection()); SchemaManager::Result result = schemaManager.upgradeToSchemaVersion( diff --git a/src/util/db/fwdsqlquery.h b/src/util/db/fwdsqlquery.h index a1369033ffb4..0ed7eef259cd 100644 --- a/src/util/db/fwdsqlquery.h +++ b/src/util/db/fwdsqlquery.h @@ -1,5 +1,4 @@ -#ifndef MIXXX_FWDSQLQUERY_H -#define MIXXX_FWDSQLQUERY_H +#pragma once #include @@ -45,7 +44,11 @@ class FwdSqlQuery: protected QSqlQuery { } bool hasError() const { - return lastError().isValid() && (lastError().type() != QSqlError::NoError); + return lastError().isValid() && + (lastError().type() != QSqlError::NoError); + } + QSqlError lastError() const { + return QSqlQuery::lastError(); } static const int BOOLEAN_FALSE = 0; @@ -112,6 +115,3 @@ class FwdSqlQuery: protected QSqlQuery { bool m_prepared; }; - - -#endif // MIXXX_FWDSQLQUERY_H