Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/library/schemamanager.cpp

Go to the documentation of this file.
00001 // schemamanager.cpp
00002 // Created 12/29/2009 by RJ Ryan (rryan@mit.edu)
00003 
00004 #include <QtCore>
00005 #include <QtDebug>
00006 
00007 #include "library/schemamanager.h"
00008 #include "widget/wwidget.h"
00009 
00010 const QString SchemaManager::SETTINGS_VERSION_STRING = "mixxx.schema.version";
00011 const QString SchemaManager::SETTINGS_MINCOMPATIBLE_STRING = "mixxx.schema.min_compatible_version";
00012 
00013 // static
00014 bool SchemaManager::upgradeToSchemaVersion(ConfigObject<ConfigValue>* config,
00015                                            QSqlDatabase& db, int targetVersion) {
00016 
00017     SettingsDAO settings(db);
00018     int currentVersion = getCurrentSchemaVersion(settings);
00019     Q_ASSERT(currentVersion >= 0);
00020 
00021     if (currentVersion == targetVersion) {
00022         qDebug() << "SchemaManager::upgradeToSchemaVersion already at version"
00023                  << targetVersion;
00024         return true;
00025     } else if (currentVersion < targetVersion) {
00026         qDebug() << "SchemaManager::upgradeToSchemaVersion upgrading"
00027                  << targetVersion-currentVersion << "versions to version"
00028                  << targetVersion;
00029     } else {
00030         qDebug() << "SchemaManager::upgradeToSchemaVersion already past target "
00031                 "version. currentVersion:"
00032                  << currentVersion << "targetVersion:"
00033                  << targetVersion;
00034 
00035         if (isBackwardsCompatible(settings, currentVersion, targetVersion)) {
00036             qDebug() << "Current schema version is backwards-compatible with" << targetVersion;
00037             return true;
00038         }
00039     }
00040 
00041     QString schemaFilename = config->getConfigPath();
00042     schemaFilename.append("schema.xml");
00043     qDebug() << "Loading schema" << schemaFilename;
00044     QDomElement schemaRoot = WWidget::openXMLFile(schemaFilename, "schema");
00045 
00046     QDomNodeList revisions = schemaRoot.childNodes();
00047 
00048     QMap<int, QDomElement> revisionMap;
00049 
00050     for (int i = 0; i < revisions.count(); i++) {
00051         QDomElement revision = revisions.at(i).toElement();
00052         QString version = revision.attribute("version");
00053         Q_ASSERT(!version.isNull());
00054         int iVersion = version.toInt();
00055         revisionMap[iVersion] = revision;
00056     }
00057 
00058     bool success = true;
00059 
00060     while (currentVersion != targetVersion) {
00061         int thisTarget;
00062         if (currentVersion > targetVersion) {
00063             thisTarget = currentVersion - 1;
00064             qDebug() << "Downgrade not yet supported.";
00065             success = false;
00066             break;
00067         } else {
00068             thisTarget = currentVersion + 1;
00069         }
00070 
00071         if (!revisionMap.contains(thisTarget)) {
00072             qDebug() << "SchemaManager::upgradeToSchemaVersion"
00073                      << "Don't know how to get to"
00074                      << thisTarget << "from" << currentVersion;
00075             success = false;
00076             break;
00077         }
00078 
00079         QDomElement revision = revisionMap[thisTarget];
00080         QDomElement eDescription = revision.firstChildElement("description");
00081         QDomElement eSql = revision.firstChildElement("sql");
00082         QString minCompatibleVersion = revision.attribute("min_compatible");
00083 
00084         // Default the min-compatible version to the current version string if
00085         // it's not in the schema.xml
00086         if (minCompatibleVersion.isNull()) {
00087             minCompatibleVersion = QString::number(thisTarget);
00088         }
00089 
00090         Q_ASSERT(!eDescription.isNull() && !eSql.isNull());
00091 
00092         QString description = eDescription.text();
00093         QString sql = eSql.text();
00094 
00095 
00096         qDebug() << "Applying version" << thisTarget << ":"
00097                  << description.trimmed();
00098 
00099         db.transaction();
00100 
00101         // TODO(XXX) We can't have semicolons in schema.xml for anything other
00102         // than statement separators.
00103         QStringList sqlStatements = sql.split(";");
00104 
00105         QStringListIterator it(sqlStatements);
00106 
00107         QSqlQuery query(db);
00108         bool result = true;
00109         while (result && it.hasNext()) {
00110             QString statement = it.next().trimmed();
00111             if (statement.isEmpty()) {
00112                 continue;
00113             }
00114             result = result && query.exec(statement);
00115             if (!result) {
00116                 qDebug() << "Failed query:"
00117                          << statement
00118                          << query.lastError();
00119             }
00120         }
00121 
00122         if (result) {
00123             currentVersion = thisTarget;
00124             settings.setValue(SETTINGS_VERSION_STRING, thisTarget);
00125             settings.setValue(SETTINGS_MINCOMPATIBLE_STRING, minCompatibleVersion);
00126             db.commit();
00127         } else {
00128             success = false;
00129             qDebug() << "Failed to move from version" << currentVersion
00130                      << "to version" << thisTarget;
00131             db.rollback();
00132             break;
00133         }
00134     }
00135 
00136     return success;
00137 }
00138 
00139 // static
00140 int SchemaManager::getCurrentSchemaVersion(SettingsDAO& settings) {
00141     QString currentSchemaVersion = settings.getValue(SETTINGS_VERSION_STRING);
00142     // May be a null string if the schema has not been created. We default the
00143     // startVersion to 0 so that we automatically try to upgrade to revision 1.
00144     int currentVersion = 0;
00145     if (!currentSchemaVersion.isNull()) {
00146         currentVersion = currentSchemaVersion.toInt();
00147     }
00148     return currentVersion;
00149 }
00150 
00151 // static
00152 bool SchemaManager::isBackwardsCompatible(SettingsDAO& settings,
00153                                           int currentVersion,
00154                                           int targetVersion) {
00155     QString backwardsCompatibleVersion =
00156             settings.getValue(SETTINGS_MINCOMPATIBLE_STRING);
00157     int iBackwardsCompatibleVersion = -1;
00158 
00159     // If the current backwards compatible schema version is not stored in the
00160     // settings table, assume the current schema version is only backwards
00161     // compatible with itself.
00162     if (backwardsCompatibleVersion.isNull()) {
00163         // rryan 11/2010 We just added the backwards compatible flags, and some
00164         // people using the Mixxx trunk are already on schema version 7. This
00165         // special case is for them. Schema version 7 is backwards compatible
00166         // with schema version 3.
00167         if (currentVersion == 7) {
00168             iBackwardsCompatibleVersion = 3;
00169         } else {
00170             iBackwardsCompatibleVersion = currentVersion;
00171         }
00172     }
00173 
00174     // If the target version is greater than the minimum compatible version of
00175     // the current schema, then the current schema is backwards compatible with
00176     // targetVersion.
00177     return iBackwardsCompatibleVersion <= targetVersion;
00178 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines