summaryrefslogtreecommitdiffstats
path: root/src/database/mixxxdb.cpp
blob: 0cee5949a1561397dfabe2e72653438dc4724cfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "database/mixxxdb.h"

#include "database/schemamanager.h"
#include "moc_mixxxdb.cpp"
#include "util/assert.h"
#include "util/logger.h"

// The schema XML is baked into the binary via Qt resources.
//static
const QString MixxxDb::kDefaultSchemaFile(":/schema.xml");

//static
const int MixxxDb::kRequiredSchemaVersion = 32;

namespace {

const mixxx::Logger kLogger("MixxxDb");

const QString kType = QStringLiteral("QSQLITE");

const QString kConnectOptions = QStringLiteral("QSQLITE_OPEN_URI");

const QString kUriPrefix = QStringLiteral("file://");

const QString kDefaultFileName = QStringLiteral("mixxxdb.sqlite");

const QString kUserName = QStringLiteral("mixxx");

const QString kPassword = QStringLiteral("mixxx");

// The connection parameters for the main Mixxx DB
mixxx::DbConnection::Params dbConnectionParams(
        const UserSettingsPointer& pConfig,
        bool inMemoryConnection) {
    mixxx::DbConnection::Params params;
    params.type = kType;
    params.connectOptions = kConnectOptions;
    params.filePath = kUriPrefix;
    const QString absFilePath =
            QDir(pConfig->getSettingsPath()).absoluteFilePath(kDefaultFileName);
    // On Windows absFilePath starts with a drive letter instead of
    // the leading '/' as required.
    // https://www.sqlite.org/c3ref/open.html#urifilenameexamples
    if (!absFilePath.startsWith(QChar('/'))) {
        params.filePath += QChar('/');
    }
    params.filePath += absFilePath;
    // Allow multiple connections to the same in-memory database by
    // using a named connection. This is needed to make the database
    // connection pool work correctly even during tests.
    //
    // See also:
    // https://www.sqlite.org/inmemorydb.html
    if (inMemoryConnection) {
        params.filePath += QStringLiteral("?mode=memory&cache=shared");
    }
    params.userName = kUserName;
    params.password = kPassword;
    return params;
}

} // anonymous namespace

MixxxDb::MixxxDb(
        const UserSettingsPointer& pConfig,
        bool inMemoryConnection)
    : m_pDbConnectionPool(std::make_shared<mixxx::DbConnectionPool>(dbConnectionParams(pConfig, inMemoryConnection), "MIXXX")) {
}

bool MixxxDb::initDatabaseSchema(
        const QSqlDatabase& database,
        const QString& schemaFile,
        int schemaVersion) {
    QString okToExit = tr("Click OK to exit.");
    QString upgradeFailed = tr("Cannot upgrade database schema");
    QString upgradeToVersionFailed =
            tr("Unable to upgrade your database schema to version %1")
            .arg(QString::number(schemaVersion));
    QString helpEmail = tr("For help with database issues contact:") + "\n" +
                           "mixxx-devel@lists.sourceforge.net";

    switch (SchemaManager(database).upgradeToSchemaVersion(schemaFile, schemaVersion)) {
        case SchemaManager::Result::CurrentVersion:
        case SchemaManager::Result::UpgradeSucceeded:
        case SchemaManager::Result::NewerVersionBackwardsCompatible:
            return true; // done
        case SchemaManager::Result::UpgradeFailed:
            QMessageBox::warning(
                    0, upgradeFailed,
                    upgradeToVersionFailed + "\n" +
                    tr("Your mixxxdb.sqlite file may be corrupt.") + "\n" +
                    tr("Try renaming it and restarting Mixxx.") + "\n" +
                    helpEmail + "\n\n" + okToExit,
                    QMessageBox::Ok);
            return false; // abort
        case SchemaManager::Result::NewerVersionIncompatible:
            QMessageBox::warning(
                    0, upgradeFailed,
                    upgradeToVersionFailed + "\n" +
                    tr("Your mixxxdb.sqlite file was created by a newer "
                       "version of Mixxx and is incompatible.") +
                    "\n\n" + okToExit,
                    QMessageBox::Ok);
            return false; // abort
        case SchemaManager::Result::SchemaError:
            QMessageBox::warning(
                    0, upgradeFailed,
                    upgradeToVersionFailed + "\n" +
                    tr("The database schema file is invalid.") + "\n" +
                    helpEmail + "\n\n" + okToExit,
                    QMessageBox::Ok);
            return false; // abort
    }
    // Suppress compiler warning
    DEBUG_ASSERT(!"unhandled switch/case");
    return false;
}