mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
fix(history): handle errors during db upgrade
This commit is contained in:
parent
dacfcdadac
commit
f72f3f714d
@ -28,7 +28,7 @@
|
|||||||
namespace {
|
namespace {
|
||||||
static constexpr int SCHEMA_VERSION = 1;
|
static constexpr int SCHEMA_VERSION = 1;
|
||||||
|
|
||||||
bool createCurrentSchema(std::shared_ptr<RawDatabase> db)
|
bool createCurrentSchema(RawDatabase& db)
|
||||||
{
|
{
|
||||||
QVector<RawDatabase::Query> queries;
|
QVector<RawDatabase::Query> queries;
|
||||||
queries += RawDatabase::Query(QStringLiteral(
|
queries += RawDatabase::Query(QStringLiteral(
|
||||||
@ -63,10 +63,10 @@ bool createCurrentSchema(std::shared_ptr<RawDatabase> db)
|
|||||||
"file_state INTEGER NOT NULL);"
|
"file_state INTEGER NOT NULL);"
|
||||||
"CREATE TABLE faux_offline_pending (id INTEGER PRIMARY KEY);"));
|
"CREATE TABLE faux_offline_pending (id INTEGER PRIMARY KEY);"));
|
||||||
queries += RawDatabase::Query(QStringLiteral("PRAGMA user_version = %1;").arg(SCHEMA_VERSION));
|
queries += RawDatabase::Query(QStringLiteral("PRAGMA user_version = %1;").arg(SCHEMA_VERSION));
|
||||||
return db->execNow(queries);
|
return db.execNow(queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNewDb(std::shared_ptr<RawDatabase> db)
|
bool isNewDb(std::shared_ptr<RawDatabase>& db, bool& success)
|
||||||
{
|
{
|
||||||
bool newDb;
|
bool newDb;
|
||||||
if (!db->execNow(RawDatabase::Query("SELECT COUNT(*) FROM sqlite_master;",
|
if (!db->execNow(RawDatabase::Query("SELECT COUNT(*) FROM sqlite_master;",
|
||||||
@ -74,12 +74,14 @@ bool isNewDb(std::shared_ptr<RawDatabase> db)
|
|||||||
newDb = row[0].toLongLong() == 0;
|
newDb = row[0].toLongLong() == 0;
|
||||||
}))) {
|
}))) {
|
||||||
db.reset();
|
db.reset();
|
||||||
return false; // TODO: propogate error
|
success = false;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
success = true;
|
||||||
return newDb;
|
return newDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dbSchema0to1(std::shared_ptr<RawDatabase> db)
|
bool dbSchema0to1(RawDatabase& db)
|
||||||
{
|
{
|
||||||
QVector<RawDatabase::Query> queries;
|
QVector<RawDatabase::Query> queries;
|
||||||
queries +=
|
queries +=
|
||||||
@ -97,7 +99,7 @@ bool dbSchema0to1(std::shared_ptr<RawDatabase> db)
|
|||||||
queries +=
|
queries +=
|
||||||
RawDatabase::Query(QStringLiteral("ALTER TABLE history ADD file_id INTEGER;"));
|
RawDatabase::Query(QStringLiteral("ALTER TABLE history ADD file_id INTEGER;"));
|
||||||
queries += RawDatabase::Query(QStringLiteral("PRAGMA user_version = 1;"));
|
queries += RawDatabase::Query(QStringLiteral("PRAGMA user_version = 1;"));
|
||||||
return db->execNow(queries);
|
return db.execNow(queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,7 +107,7 @@ bool dbSchema0to1(std::shared_ptr<RawDatabase> db)
|
|||||||
* @note On future alterations of the database all you have to do is bump the SCHEMA_VERSION
|
* @note On future alterations of the database all you have to do is bump the SCHEMA_VERSION
|
||||||
* variable and add another case to the switch statement below. Make sure to fall through on each case.
|
* variable and add another case to the switch statement below. Make sure to fall through on each case.
|
||||||
*/
|
*/
|
||||||
void dbSchemaUpgrade(std::shared_ptr<RawDatabase> db)
|
void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
|
||||||
{
|
{
|
||||||
int64_t databaseSchemaVersion;
|
int64_t databaseSchemaVersion;
|
||||||
|
|
||||||
@ -127,22 +129,36 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase> db)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<RawDatabase::Query> queries;
|
|
||||||
// Make sure to handle the un-created case as well in the following upgrade code
|
|
||||||
switch (databaseSchemaVersion) {
|
switch (databaseSchemaVersion) {
|
||||||
case 0:
|
case 0: {
|
||||||
// Note: 0 is a special version that is actually two versions.
|
// Note: 0 is a special version that is actually two versions.
|
||||||
// possibility 1) it is a newly created database and it neesds the current schema to be created.
|
// possibility 1) it is a newly created database and it neesds the current schema to be created.
|
||||||
// possibility 2) it is a old existing database, before version 1 and before we saved schema version,
|
// possibility 2) it is a old existing database, before version 1 and before we saved schema version,
|
||||||
// and needs to be updated.
|
// and needs to be updated.
|
||||||
if (isNewDb(db)) {
|
bool success = false;
|
||||||
createCurrentSchema(db);
|
const bool newDb = isNewDb(db, success);
|
||||||
|
if (!success) {
|
||||||
|
qCritical() << "Failed to create current db schema";
|
||||||
|
db.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newDb) {
|
||||||
|
if (!createCurrentSchema(*db)) {
|
||||||
|
qCritical() << "Failed to create current db schema";
|
||||||
|
db.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
qDebug() << "Database created at schema version" << SCHEMA_VERSION;
|
qDebug() << "Database created at schema version" << SCHEMA_VERSION;
|
||||||
break; // new db is the only case where we don't incrementally upgrade through each version
|
break; // new db is the only case where we don't incrementally upgrade through each version
|
||||||
} else {
|
} else {
|
||||||
dbSchema0to1(db);
|
if (!dbSchema0to1(*db)) {
|
||||||
|
qCritical() << "Failed to upgrade db to schema version 1, aborting";
|
||||||
|
db.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
qDebug() << "Database upgraded incrementally to schema version 1";
|
qDebug() << "Database upgraded incrementally to schema version 1";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// fallthrough
|
// fallthrough
|
||||||
// case 1:
|
// case 1:
|
||||||
// dbSchema1to2(queries);
|
// dbSchema1to2(queries);
|
||||||
|
@ -114,24 +114,29 @@ void TestDbSchema::testCreation()
|
|||||||
{
|
{
|
||||||
QVector<RawDatabase::Query> queries;
|
QVector<RawDatabase::Query> queries;
|
||||||
auto db = std::shared_ptr<RawDatabase>{new RawDatabase{"testCreation.db", {}, {}}};
|
auto db = std::shared_ptr<RawDatabase>{new RawDatabase{"testCreation.db", {}, {}}};
|
||||||
QVERIFY(createCurrentSchema(db));
|
QVERIFY(createCurrentSchema(*db));
|
||||||
verifyDb(db, schema1);
|
verifyDb(db, schema1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDbSchema::testIsNewDb()
|
void TestDbSchema::testIsNewDb()
|
||||||
{
|
{
|
||||||
auto db = std::shared_ptr<RawDatabase>{new RawDatabase{"testIsNewDbTrue.db", {}, {}}};
|
auto db = std::shared_ptr<RawDatabase>{new RawDatabase{"testIsNewDbTrue.db", {}, {}}};
|
||||||
QVERIFY(isNewDb(db) == true);
|
bool success = false;
|
||||||
|
bool newDb = isNewDb(db, success);
|
||||||
|
QVERIFY(success);
|
||||||
|
QVERIFY(newDb == true);
|
||||||
db = std::shared_ptr<RawDatabase>{new RawDatabase{"testIsNewDbFalse.db", {}, {}}};
|
db = std::shared_ptr<RawDatabase>{new RawDatabase{"testIsNewDbFalse.db", {}, {}}};
|
||||||
createSchemaAtVersion(db, schema0);
|
createSchemaAtVersion(db, schema0);
|
||||||
QVERIFY(isNewDb(db) == false);
|
newDb = isNewDb(db, success);
|
||||||
|
QVERIFY(success);
|
||||||
|
QVERIFY(newDb == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDbSchema::test0to1()
|
void TestDbSchema::test0to1()
|
||||||
{
|
{
|
||||||
auto db = std::shared_ptr<RawDatabase>{new RawDatabase{"test0to1.db", {}, {}}};
|
auto db = std::shared_ptr<RawDatabase>{new RawDatabase{"test0to1.db", {}, {}}};
|
||||||
createSchemaAtVersion(db, schema0);
|
createSchemaAtVersion(db, schema0);
|
||||||
QVERIFY(dbSchema0to1(db));
|
QVERIFY(dbSchema0to1(*db));
|
||||||
verifyDb(db, schema1);
|
verifyDb(db, schema1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user