210 lines
5.1 KiB
C++
210 lines
5.1 KiB
C++
/*
|
|
Copyright 2011 Grégory Soutadé
|
|
|
|
This file is part of KissCount.
|
|
|
|
KissCount is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
KissCount is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with KissCount. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <QString>
|
|
#include <QMessageBox>
|
|
#include <QSqlQuery>
|
|
#include <QSqlError>
|
|
#include <QVariant>
|
|
#include <QSqlRecord>
|
|
|
|
#include "Database.hpp"
|
|
|
|
#define ON_ERROR(m) \
|
|
QMessageBox::critical(0, _("Error"), m); \
|
|
throw m;
|
|
|
|
typedef void (*update_func)(QSqlDatabase& _db) ;
|
|
|
|
#define UPDATE_TABLE(from, to, step) EXECUTE_SQL_UPDATE_WITH_CODE(req, , throw std::string("Error while upgrading from version " from " to version " to ", step " step);, });
|
|
|
|
static void Version_1_to_2(QSqlDatabase& _db)
|
|
{
|
|
QString req ;
|
|
|
|
/* Category */
|
|
req = "ALTER TABLE category ADD fix_cost CHAR(1)";
|
|
|
|
UPDATE_TABLE("1", "2", "1");
|
|
|
|
req = "UPDATE category SET fix_cost='0'";
|
|
|
|
UPDATE_TABLE("1", "2", "2");
|
|
|
|
req = "UPDATE category SET fix_cost='1' WHERE id IN (";
|
|
req += "SELECT MIN(category.id) FROM category, user WHERE category.user = user.id";
|
|
req += ")";
|
|
|
|
UPDATE_TABLE("1", "2", "3");
|
|
|
|
/* Account */
|
|
req = "ALTER TABLE account ADD virtual CHAR(1)";
|
|
|
|
UPDATE_TABLE("1", "2", "4");
|
|
|
|
req = "UPDATE account SET virtual='0'";
|
|
|
|
UPDATE_TABLE("1", "2", "5");
|
|
|
|
/* Operation */
|
|
req = "ALTER TABLE operation ADD virtual CHAR(1)";
|
|
|
|
UPDATE_TABLE("1", "2", "6");
|
|
|
|
req = "UPDATE operation SET virtual='0'";
|
|
|
|
UPDATE_TABLE("1", "2", "7");
|
|
|
|
/* Import Pattern */
|
|
req = "CREATE TABLE import_pattern(id INTEGER PRIMARY KEY, user REFERENCES user(id), description VARCHAR(255), pattern VARCHAR(255), account REFERENCES account(id), category REFERENCES category(id))";
|
|
|
|
UPDATE_TABLE("1", "2", "8");
|
|
}
|
|
|
|
static void Version_2_to_3(QSqlDatabase& _db)
|
|
{
|
|
QString req ;
|
|
|
|
/* Account */
|
|
req = "ALTER TABLE account ADD hidden CHAR(1)";
|
|
|
|
UPDATE_TABLE("2", "3", "1");
|
|
|
|
req = "UPDATE account SET hidden='0'";
|
|
|
|
UPDATE_TABLE("2", "3", "2");
|
|
|
|
ON_ERROR(_("Cannot update database version 2 to version 3 because some columns needs to be deleted."));
|
|
}
|
|
|
|
static void Version_3_to_4(QSqlDatabase& _db)
|
|
{
|
|
QString req ;
|
|
|
|
req = "CREATE TABLE tag(id INTEGER PRIMARY KEY, user REFERENCES user(id), name VARCHAR(255));";
|
|
|
|
UPDATE_TABLE("3", "3", "1");
|
|
|
|
/* Account */
|
|
req = "ALTER TABLE operation ADD tag REFERENCES tag(id)";
|
|
|
|
UPDATE_TABLE("3", "3", "2");
|
|
|
|
req = "UPDATE operation SET tag='0'";
|
|
|
|
UPDATE_TABLE("3", "3", "3");
|
|
}
|
|
|
|
static void Version_4_to_5(QSqlDatabase& _db)
|
|
{
|
|
QString req ;
|
|
|
|
/* Account */
|
|
req = "ALTER TABLE account ADD COLUMN start DATE;";
|
|
UPDATE_TABLE("4", "5", "5");
|
|
|
|
req = "ALTER TABLE account ADD COLUMN end DATE;";
|
|
UPDATE_TABLE("4", "5", "6");
|
|
|
|
req = "UPDATE account SET start='1900-01-01', end='2050-12-31';";
|
|
UPDATE_TABLE("4", "5", "11");
|
|
}
|
|
|
|
static update_func updates[] = {
|
|
Version_1_to_2,
|
|
Version_2_to_3,
|
|
Version_3_to_4,
|
|
Version_4_to_5
|
|
};
|
|
|
|
void Database::CheckDatabaseVersion()
|
|
{
|
|
QString req ;
|
|
QSqlRecord set ;
|
|
QSqlQuery query(_db);
|
|
long int version;
|
|
int i;
|
|
|
|
req = "SELECT db_version FROM kisscount";
|
|
|
|
EXECUTE_SQL_QUERY_WITH_CODE(req, , ON_ERROR("Unable to get database version"), {});
|
|
|
|
query.next();
|
|
|
|
set = query.record();
|
|
|
|
if (!(version = set.value("db_version").toInt()))
|
|
{
|
|
ON_ERROR("Invalid database version");
|
|
}
|
|
|
|
if (version == Database::VERSION) return;
|
|
|
|
if (version > Database::VERSION)
|
|
{
|
|
ON_ERROR("Your current version of KissCount is too old and can't load this database. Please upgrade KissCount");
|
|
}
|
|
|
|
version--;
|
|
|
|
// Maybe one update is impossible
|
|
for(i=version; i<Database::VERSION-1; i++)
|
|
{
|
|
if (!updates[i])
|
|
{
|
|
ON_ERROR("The database cannot be upgraded. Please use an older version of KissCount");
|
|
}
|
|
}
|
|
|
|
if (QMessageBox::question(0, "KissCount", "You use an old database model. KissCount will try to upgrade it to the lastest version")
|
|
== QMessageBox::No)
|
|
throw std::string("can't load this database");
|
|
|
|
_db.transaction();
|
|
|
|
try
|
|
{
|
|
for(i=version; i<Database::VERSION-1; i++)
|
|
{
|
|
updates[i](_db);
|
|
}
|
|
|
|
req = "UPDATE kisscount SET db_version='" + QString::number(Database::VERSION) + "'";
|
|
|
|
EXECUTE_SQL_UPDATE_WITH_CODE(req, , throw std::string("Unable to set new database version"), {});
|
|
}
|
|
catch (std::string e)
|
|
{
|
|
std::cout << e << std::endl;
|
|
|
|
_db.rollback();
|
|
|
|
QMessageBox::critical(0, _("Error"), _("Unable to upgrade Database"));
|
|
|
|
throw e;
|
|
}
|
|
|
|
_db.commit();
|
|
|
|
QMessageBox::information(0, "KissCount", "Database upgrade successful !");
|
|
}
|
|
|
|
|