2016-05-12 14:08:58 +08:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Nut project.
|
|
|
|
|
** https://github.com/HamedMasafi/Nut
|
|
|
|
|
**
|
|
|
|
|
** Nut is free software: you can redistribute it and/or modify
|
|
|
|
|
** it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
** (at your option) any later version.
|
|
|
|
|
**
|
|
|
|
|
** Nut 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 Lesser General Public License for more details.
|
|
|
|
|
**
|
|
|
|
|
** You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
** along with Nut. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
**
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include <QtCore/QMetaProperty>
|
|
|
|
|
#include <QtCore/QDebug>
|
|
|
|
|
#include <QtCore/QJsonDocument>
|
|
|
|
|
#include <QtCore/QJsonObject>
|
|
|
|
|
|
|
|
|
|
#include <QtSql/QSqlDatabase>
|
|
|
|
|
#include <QtSql/QSqlError>
|
|
|
|
|
#include <QtSql/QSqlQuery>
|
|
|
|
|
#include <QtSql/QSqlResult>
|
|
|
|
|
|
|
|
|
|
#include "database.h"
|
|
|
|
|
#include "table.h"
|
|
|
|
|
#include "tableset.h"
|
|
|
|
|
#include "database_p.h"
|
2017-02-01 18:01:21 +08:00
|
|
|
#include "defines.h"
|
2016-05-21 16:09:03 +08:00
|
|
|
#include "tablemodel.h"
|
2017-10-07 18:26:05 +08:00
|
|
|
#include "generators/postgresqlgenerator.h"
|
|
|
|
|
#include "generators/mysqlgenerator.h"
|
|
|
|
|
#include "generators/sqlitegenerator.h"
|
|
|
|
|
#include "generators/sqlservergenerator.h"
|
2016-05-12 14:08:58 +08:00
|
|
|
#include "query.h"
|
2018-01-09 17:57:31 +08:00
|
|
|
#include "changelogtable.h"
|
2016-05-12 14:08:58 +08:00
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <cstdarg>
|
|
|
|
|
|
2017-02-01 18:01:21 +08:00
|
|
|
#define __CHANGE_LOG_TABLE_NAME "__change_logs"
|
|
|
|
|
|
|
|
|
|
NUT_BEGIN_NAMESPACE
|
|
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
qulonglong DatabasePrivate::lastId = 0;
|
2017-05-28 23:08:59 +08:00
|
|
|
QMap<QString, DatabaseModel> DatabasePrivate::allTableMaps;
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2018-01-08 22:54:06 +08:00
|
|
|
DatabasePrivate::DatabasePrivate(Database *parent) : q_ptr(parent), isDatabaseNew(false)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-27 23:40:10 +08:00
|
|
|
bool DatabasePrivate::open(bool update)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
2018-01-09 00:59:16 +08:00
|
|
|
if (db.isOpen())
|
|
|
|
|
return true;
|
2017-02-01 18:01:21 +08:00
|
|
|
Q_Q(Database);
|
2017-05-28 23:08:59 +08:00
|
|
|
// if (update)
|
2017-05-25 23:46:54 +08:00
|
|
|
connectionName = q->metaObject()->className()
|
|
|
|
|
+ QString::number(DatabasePrivate::lastId);
|
2017-02-01 18:01:21 +08:00
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
db = QSqlDatabase::addDatabase(driver, connectionName);
|
|
|
|
|
db.setHostName(hostName);
|
2018-01-08 22:54:06 +08:00
|
|
|
db.setPort(port);
|
2016-05-12 14:08:58 +08:00
|
|
|
db.setDatabaseName(databaseName);
|
|
|
|
|
db.setUserName(userName);
|
|
|
|
|
db.setPassword(password);
|
|
|
|
|
bool ok = db.open();
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (!ok) {
|
|
|
|
|
qWarning("Could not connect to database, error = %s",
|
|
|
|
|
db.lastError().text().toLocal8Bit().data());
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (db.lastError().text().contains("database \"" + databaseName
|
|
|
|
|
+ "\" does not exist")
|
|
|
|
|
|| db.lastError().text().contains("Cannot open database")
|
|
|
|
|
|| db.lastError().text().contains("Unknown database '"
|
|
|
|
|
+ databaseName + "'")) {
|
2018-01-08 17:08:10 +08:00
|
|
|
|
|
|
|
|
db.close();
|
2016-05-21 16:09:03 +08:00
|
|
|
db.setDatabaseName(sqlGenertor->masterDatabaseName(databaseName));
|
2016-05-12 14:08:58 +08:00
|
|
|
ok = db.open();
|
2016-06-05 20:22:26 +08:00
|
|
|
qDebug("Creating database");
|
2017-05-25 23:46:54 +08:00
|
|
|
if (ok) {
|
2016-05-12 14:08:58 +08:00
|
|
|
db.exec("CREATE DATABASE " + databaseName);
|
|
|
|
|
db.close();
|
2016-05-21 16:09:03 +08:00
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
if (db.lastError().type() != QSqlError::NoError) {
|
2017-05-25 23:46:54 +08:00
|
|
|
qWarning("Creating database error: %s",
|
|
|
|
|
db.lastError().text().toLatin1().data());
|
2018-01-08 17:08:10 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
2016-05-21 16:09:03 +08:00
|
|
|
|
2018-01-08 22:54:06 +08:00
|
|
|
isDatabaseNew = true;
|
2017-05-27 23:40:10 +08:00
|
|
|
return open(update);
|
2017-05-25 23:46:54 +08:00
|
|
|
} else {
|
|
|
|
|
qWarning("Unknown error detecting change logs, %s",
|
|
|
|
|
db.lastError().text().toLatin1().data());
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
if(update)
|
2017-05-27 23:40:10 +08:00
|
|
|
return updateDatabase();
|
|
|
|
|
else
|
|
|
|
|
return true;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DatabasePrivate::updateDatabase()
|
|
|
|
|
{
|
2016-06-05 20:22:26 +08:00
|
|
|
Q_Q(Database);
|
|
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
if (!getCurrectScheema())
|
|
|
|
|
return true;
|
|
|
|
|
|
2018-01-08 22:54:06 +08:00
|
|
|
DatabaseModel last = isDatabaseNew ? DatabaseModel() : getLastScheema();
|
2016-05-21 16:09:03 +08:00
|
|
|
DatabaseModel current = currentModel;
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (last == current) {
|
2016-06-05 20:22:26 +08:00
|
|
|
qDebug("Databse is up-to-date");
|
2016-05-12 14:08:58 +08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (!last.count())
|
2016-06-05 20:22:26 +08:00
|
|
|
qDebug("Databse is new");
|
2016-05-21 16:09:03 +08:00
|
|
|
else
|
2016-06-05 20:22:26 +08:00
|
|
|
qDebug("Databse is changed");
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QStringList sql = sqlGenertor->diff(last, current);
|
2018-01-08 17:08:10 +08:00
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
db.transaction();
|
2017-05-25 23:46:54 +08:00
|
|
|
foreach (QString s, sql) {
|
2016-05-12 14:08:58 +08:00
|
|
|
db.exec(s);
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (db.lastError().type() != QSqlError::NoError)
|
2018-01-08 17:08:10 +08:00
|
|
|
qWarning("Error executing sql command `%s`, %s",
|
|
|
|
|
qPrintable(s),
|
2017-05-25 23:46:54 +08:00
|
|
|
db.lastError().text().toLatin1().data());
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
2018-01-08 17:08:10 +08:00
|
|
|
putModelToDatabase();
|
2016-05-12 14:08:58 +08:00
|
|
|
bool ok = db.commit();
|
|
|
|
|
|
2017-06-12 00:50:43 +08:00
|
|
|
if (db.lastError().type() == QSqlError::NoError) {
|
2016-06-05 20:22:26 +08:00
|
|
|
|
2017-10-07 13:38:09 +08:00
|
|
|
q->databaseUpdated(last.version(), current.version());
|
2016-06-05 20:22:26 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
for (int i = 0; i < q->metaObject()->methodCount(); i++) {
|
2016-06-05 20:22:26 +08:00
|
|
|
QMetaMethod m = q->metaObject()->method(i);
|
2017-10-07 13:38:09 +08:00
|
|
|
if (m.name() == "update" + current.version()) {
|
2016-06-05 20:22:26 +08:00
|
|
|
m.invoke(q, Qt::DirectConnection,
|
2017-10-07 13:38:09 +08:00
|
|
|
Q_ARG(QString, current.version()));
|
2016-06-05 20:22:26 +08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-25 23:46:54 +08:00
|
|
|
} else {
|
|
|
|
|
qWarning("Unable update database, error = %s",
|
|
|
|
|
db.lastError().text().toLatin1().data());
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-28 23:08:59 +08:00
|
|
|
bool DatabasePrivate::getCurrectScheema()
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
|
|
|
|
Q_Q(Database);
|
2017-08-10 23:09:41 +08:00
|
|
|
|
2018-01-08 22:54:06 +08:00
|
|
|
//is not first instanicate of this class
|
2017-05-28 23:08:59 +08:00
|
|
|
if (allTableMaps.contains(q->metaObject()->className())) {
|
|
|
|
|
currentModel = allTableMaps[q->metaObject()->className()];
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
tables.clear();
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
// TODO: change logs must not be in model
|
2018-01-09 21:04:21 +08:00
|
|
|
int changeLogTypeId = qRegisterMetaType<ChangeLogTable*>();
|
2017-05-25 23:46:54 +08:00
|
|
|
currentModel.append(
|
|
|
|
|
new TableModel(changeLogTypeId, __CHANGE_LOG_TABLE_NAME));
|
|
|
|
|
tables.insert(ChangeLogTable::staticMetaObject.className(),
|
|
|
|
|
__CHANGE_LOG_TABLE_NAME);
|
2017-02-01 18:01:21 +08:00
|
|
|
|
|
|
|
|
changeLogs = new TableSet<ChangeLogTable>(q);
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
for (int i = 0; i < q->metaObject()->classInfoCount(); i++) {
|
2016-05-12 14:08:58 +08:00
|
|
|
QMetaClassInfo ci = q->metaObject()->classInfo(i);
|
2018-01-09 17:57:31 +08:00
|
|
|
QString ciName = QString(ci.name())
|
|
|
|
|
.replace(__nut_NAME_PERFIX, "")
|
|
|
|
|
.replace("\"", "");
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (ciName.startsWith(__nut_TABLE))
|
2016-06-05 20:22:26 +08:00
|
|
|
tables.insert(ciName.split(" ").at(1), ci.value());
|
2016-05-21 16:09:03 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (ciName == __nut_DB_VERSION) {
|
2017-10-07 13:38:09 +08:00
|
|
|
currentModel.setVersion(QString(ci.value()));
|
|
|
|
|
|
|
|
|
|
/* TODO: remove
|
2017-05-25 23:46:54 +08:00
|
|
|
QStringList version
|
|
|
|
|
= QString(ci.value()).replace("\"", "").split('.');
|
2016-05-21 16:09:03 +08:00
|
|
|
bool ok = false;
|
2017-05-25 23:46:54 +08:00
|
|
|
if (version.length() == 1) {
|
2017-10-07 13:38:09 +08:00
|
|
|
currentModel.setVersion(version.at(0).toInt(&ok));
|
2017-05-25 23:46:54 +08:00
|
|
|
} else if (version.length() == 2) {
|
2016-05-21 16:09:03 +08:00
|
|
|
currentModel.setVersionMajor(version.at(0).toInt(&ok));
|
|
|
|
|
currentModel.setVersionMinor(version.at(1).toInt(&ok));
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (!ok)
|
|
|
|
|
qFatal("NUT_DB_VERSION macro accept version in format 'x' or "
|
2017-10-07 13:38:09 +08:00
|
|
|
"'x[.y]' only, and x,y must be integer values\n");*/
|
2016-05-21 16:09:03 +08:00
|
|
|
}
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
for (int i = 1; i < q->metaObject()->propertyCount(); i++) {
|
2016-05-12 14:08:58 +08:00
|
|
|
QMetaProperty tableProperty = q->metaObject()->property(i);
|
2016-06-05 20:22:26 +08:00
|
|
|
int typeId = QMetaType::type(tableProperty.typeName());
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (tables.values().contains(tableProperty.name())
|
2017-08-10 23:09:41 +08:00
|
|
|
&& (unsigned)typeId >= QVariant::UserType) {
|
2016-05-21 16:09:03 +08:00
|
|
|
TableModel *sch = new TableModel(typeId, tableProperty.name());
|
2016-05-12 14:08:58 +08:00
|
|
|
currentModel.append(sch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-10 06:08:19 +08:00
|
|
|
foreach (TableModel *table, currentModel)
|
|
|
|
|
foreach (RelationModel *fk, table->foregionKeys())
|
2017-08-10 23:09:41 +08:00
|
|
|
fk->table = currentModel.tableByClassName(fk->className);
|
2017-05-28 23:08:59 +08:00
|
|
|
|
|
|
|
|
allTableMaps.insert(q->metaObject()->className(), currentModel);
|
|
|
|
|
return true;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DatabaseModel DatabasePrivate::getLastScheema()
|
|
|
|
|
{
|
2017-08-10 23:09:41 +08:00
|
|
|
ChangeLogTable *u = changeLogs->query()
|
|
|
|
|
->orderBy(!ChangeLogTable::idField())
|
|
|
|
|
->first();
|
|
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
// DatabaseModel ret(q->metaObject()->className());
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (u) {
|
|
|
|
|
QJsonObject json
|
|
|
|
|
= QJsonDocument::fromJson(
|
|
|
|
|
QByteArray(u->data().toLocal8Bit().data())).object();
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
DatabaseModel ret = json;
|
|
|
|
|
return ret;
|
|
|
|
|
/*
|
2016-05-12 14:08:58 +08:00
|
|
|
foreach (QString key, json.keys()) {
|
2016-05-21 16:09:03 +08:00
|
|
|
TableModel *sch = new TableModel(json.value(key).toObject(), key);
|
2016-05-12 14:08:58 +08:00
|
|
|
ret.append(sch);
|
2018-01-08 17:08:10 +08:00
|
|
|
}*/
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
2018-01-08 17:08:10 +08:00
|
|
|
return DatabaseModel();
|
2017-02-01 18:01:21 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
// QSqlQuery query = q->exec("select * from __change_logs order by id
|
|
|
|
|
// desc limit 1");
|
|
|
|
|
// DatabaseModel ret;
|
|
|
|
|
// if(query.next()){
|
|
|
|
|
// QJsonObject json =
|
|
|
|
|
// QJsonDocument::fromJson(query.value("data").toByteArray()).object();
|
2017-02-01 18:01:21 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
// foreach (QString key, json.keys()) {
|
|
|
|
|
// TableModel *sch = new TableModel(json.value(key).toObject(),
|
|
|
|
|
// key);
|
|
|
|
|
// ret.append(sch);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// return ret;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
bool DatabasePrivate::putModelToDatabase()
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
2016-05-21 16:09:03 +08:00
|
|
|
Q_Q(Database);
|
2017-02-01 18:01:21 +08:00
|
|
|
DatabaseModel current = currentModel;
|
|
|
|
|
/*current.remove(__CHANGE_LOG_TABLE_NAME)*/;
|
|
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
ChangeLogTable *changeLog = new ChangeLogTable();
|
2017-02-01 18:01:21 +08:00
|
|
|
changeLog->setData(QJsonDocument(current.toJson()).toJson());
|
2017-10-07 13:38:09 +08:00
|
|
|
changeLog->setVersion(current.version());
|
2016-05-21 16:09:03 +08:00
|
|
|
changeLogs->append(changeLog);
|
|
|
|
|
q->saveChanges();
|
|
|
|
|
changeLog->deleteLater();
|
|
|
|
|
|
|
|
|
|
return true;
|
2017-02-01 18:01:21 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
// QSqlQuery query(db);
|
|
|
|
|
// query.prepare("insert into __change_logs (data) values (:data)");
|
|
|
|
|
// query.bindValue(":data",
|
|
|
|
|
// QString(QJsonDocument(currentModel.toJson()).toJson()));
|
|
|
|
|
// bool ret = query.exec();
|
|
|
|
|
// if(query.lastError().type() != QSqlError::NoError)
|
|
|
|
|
// qWarning(QString("storeScheemaInDB" +
|
|
|
|
|
// query.lastError().text()).toLatin1().data());
|
|
|
|
|
// return ret;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DatabasePrivate::createChangeLogs()
|
|
|
|
|
{
|
2017-05-25 23:46:54 +08:00
|
|
|
// currentModel.model("change_log")
|
2017-08-10 23:09:41 +08:00
|
|
|
QString diff = sqlGenertor->diff(0, currentModel.tableByName("__change_log"));
|
2016-05-12 14:08:58 +08:00
|
|
|
|
|
|
|
|
db.exec(diff);
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
/*!
|
|
|
|
|
* \class Database
|
|
|
|
|
* \brief Database class
|
|
|
|
|
*/
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
Database::Database(QObject *parent)
|
|
|
|
|
: QObject(parent), d_ptr(new DatabasePrivate(this))
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
2017-02-01 18:01:21 +08:00
|
|
|
DatabasePrivate::lastId++;
|
2018-01-09 17:57:31 +08:00
|
|
|
qRegisterMetaType<ChangeLogTable*>();
|
2017-02-01 18:01:21 +08:00
|
|
|
}
|
|
|
|
|
|
2018-01-08 22:54:06 +08:00
|
|
|
Database::Database(const Database &other)
|
|
|
|
|
: QObject(other.parent()), d_ptr(new DatabasePrivate(this))
|
|
|
|
|
{
|
|
|
|
|
DatabasePrivate::lastId++;
|
|
|
|
|
|
|
|
|
|
setDriver(other.driver());
|
|
|
|
|
setHostName(other.hostName());
|
|
|
|
|
setPort(other.port());
|
|
|
|
|
setDatabaseName(other.databaseName());
|
|
|
|
|
setUserName(other.userName());
|
|
|
|
|
setPassword(other.password());
|
2018-01-09 17:57:31 +08:00
|
|
|
qRegisterMetaType<ChangeLogTable*>();
|
2018-01-08 22:54:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Database::Database(const QSqlDatabase &other)
|
2017-02-01 18:01:21 +08:00
|
|
|
{
|
2018-01-09 00:59:16 +08:00
|
|
|
//TODO: make a polish here
|
2017-02-01 18:01:21 +08:00
|
|
|
DatabasePrivate::lastId++;
|
|
|
|
|
|
2018-01-09 00:59:16 +08:00
|
|
|
// setDriver(other.driver());
|
2017-02-01 18:01:21 +08:00
|
|
|
setHostName(other.hostName());
|
2018-01-08 22:54:06 +08:00
|
|
|
setPort(other.port());
|
2017-02-01 18:01:21 +08:00
|
|
|
setDatabaseName(other.databaseName());
|
|
|
|
|
setUserName(other.userName());
|
|
|
|
|
setPassword(other.password());
|
2018-01-09 17:57:31 +08:00
|
|
|
qRegisterMetaType<ChangeLogTable*>();
|
2017-05-25 23:46:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Database::~Database()
|
|
|
|
|
{
|
2017-05-29 23:29:39 +08:00
|
|
|
Q_D(Database);
|
|
|
|
|
if (d->db.isOpen())
|
|
|
|
|
d->db.close();
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (d_ptr)
|
|
|
|
|
delete d_ptr;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Database::databaseName() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->databaseName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Database::hostName() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->hostName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Database::port() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Database::userName() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->userName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Database::password() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->password;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-10 16:14:31 +08:00
|
|
|
/*!
|
|
|
|
|
* \brief Database::connectionName
|
|
|
|
|
* \return Connection name of current Database \l QSqlDatabase::connectionName
|
|
|
|
|
*/
|
2016-05-12 14:08:58 +08:00
|
|
|
QString Database::connectionName() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->connectionName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Database::driver() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->driver;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
/*!
|
|
|
|
|
* \brief Database::model
|
|
|
|
|
* \return The model of this database
|
|
|
|
|
*/
|
2016-05-12 14:08:58 +08:00
|
|
|
DatabaseModel Database::model() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->currentModel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Database::tableName(QString className)
|
|
|
|
|
{
|
2017-08-10 23:09:41 +08:00
|
|
|
TableModel *m = model().tableByClassName(className);
|
2017-08-09 21:19:35 +08:00
|
|
|
if (m)
|
|
|
|
|
return m->name();
|
|
|
|
|
else
|
|
|
|
|
return QString::null;;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Database::setDatabaseName(QString databaseName)
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
|
|
|
|
d->databaseName = databaseName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Database::setHostName(QString hostName)
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
|
|
|
|
d->hostName = hostName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Database::setPort(int port)
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
|
|
|
|
d->port = port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Database::setUserName(QString username)
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
|
|
|
|
d->userName = username;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Database::setPassword(QString password)
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
|
|
|
|
d->password = password;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Database::setConnectionName(QString connectionName)
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
|
|
|
|
d->connectionName = connectionName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Database::setDriver(QString driver)
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
2017-08-10 23:09:41 +08:00
|
|
|
d->driver = driver.toUpper();
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SqlGeneratorBase *Database::sqlGenertor() const
|
|
|
|
|
{
|
|
|
|
|
Q_D(const Database);
|
|
|
|
|
return d->sqlGenertor;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-07 13:38:09 +08:00
|
|
|
void Database::databaseUpdated(QString oldVersion, QString newVersion)
|
2016-06-05 20:22:26 +08:00
|
|
|
{
|
2017-10-07 13:38:09 +08:00
|
|
|
Q_UNUSED(oldVersion);
|
|
|
|
|
Q_UNUSED(newVersion);
|
2016-06-05 20:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
2017-05-27 23:40:10 +08:00
|
|
|
|
2018-01-09 21:04:21 +08:00
|
|
|
/**
|
|
|
|
|
* @brief Database::open
|
|
|
|
|
* Opens the database connection using the current connection values.
|
|
|
|
|
* Returns true on success; otherwise returns false.
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
2016-05-12 14:08:58 +08:00
|
|
|
bool Database::open()
|
2017-05-27 23:40:10 +08:00
|
|
|
{
|
|
|
|
|
return open(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Database::open(bool updateDatabase)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
|
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (d->driver == "QPSQL" || d->driver == "QPSQL7")
|
2016-05-24 14:47:37 +08:00
|
|
|
d->sqlGenertor = new PostgreSqlGenerator(this);
|
2016-05-21 16:09:03 +08:00
|
|
|
else if (d->driver == "QMYSQL" || d->driver == "QMYSQL3")
|
2016-05-24 14:47:37 +08:00
|
|
|
d->sqlGenertor = new MySqlGenerator(this);
|
2016-05-21 16:09:03 +08:00
|
|
|
else if (d->driver == "QSQLITE" || d->driver == "QSQLITE3")
|
2016-05-24 14:47:37 +08:00
|
|
|
d->sqlGenertor = new SqliteGenerator(this);
|
2017-05-25 23:46:54 +08:00
|
|
|
else if (d->driver == "QODBC" || d->driver == "QODBC3") {
|
2016-05-21 16:09:03 +08:00
|
|
|
QString driverName = QString::null;
|
|
|
|
|
QStringList parts = d->databaseName.toLower().split(';');
|
|
|
|
|
foreach (QString p, parts)
|
2017-05-25 23:46:54 +08:00
|
|
|
if (p.trimmed().startsWith("driver="))
|
2017-02-01 18:01:21 +08:00
|
|
|
driverName = p.split('=').at(1).toLower().trimmed();
|
2016-05-21 16:09:03 +08:00
|
|
|
|
2017-06-02 14:17:31 +08:00
|
|
|
// if (driverName == "{sql server}")
|
2016-05-24 14:47:37 +08:00
|
|
|
d->sqlGenertor = new SqlServerGenerator(this);
|
2017-05-25 23:46:54 +08:00
|
|
|
// TODO: add ODBC driver for mysql, postgres, ...
|
2016-05-21 16:09:03 +08:00
|
|
|
}
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
if (!d->sqlGenertor) {
|
2017-06-04 16:16:06 +08:00
|
|
|
qFatal("Sql generator for driver %s not found",
|
2017-05-25 23:46:54 +08:00
|
|
|
driver().toLatin1().constData());
|
2016-05-12 14:08:58 +08:00
|
|
|
return false;
|
2017-05-25 23:46:54 +08:00
|
|
|
} else {
|
2017-05-27 23:40:10 +08:00
|
|
|
return d->open(updateDatabase);
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
void Database::close()
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
|
|
|
|
d->db.close();
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
QSqlQuery Database::exec(QString sql)
|
|
|
|
|
{
|
|
|
|
|
Q_D(Database);
|
2017-02-01 18:01:21 +08:00
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
QSqlQuery q = d->db.exec(sql);
|
2017-05-25 23:46:54 +08:00
|
|
|
if (d->db.lastError().type() != QSqlError::NoError)
|
2017-05-28 23:08:59 +08:00
|
|
|
qWarning("Error executing sql command: %s; Command=%s",
|
|
|
|
|
d->db.lastError().text().toLatin1().data(),
|
|
|
|
|
sql.toUtf8().constData());
|
2016-05-12 14:08:58 +08:00
|
|
|
return q;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Database::add(TableSetBase *t)
|
|
|
|
|
{
|
2017-09-10 22:18:20 +08:00
|
|
|
Q_D(Database);
|
|
|
|
|
d->tableSets.insert(t);
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
2017-09-10 22:18:20 +08:00
|
|
|
int Database::saveChanges(bool cleanUp)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
2017-09-10 22:18:20 +08:00
|
|
|
Q_D(Database);
|
2017-05-28 23:08:59 +08:00
|
|
|
int rowsAffected = 0;
|
2017-09-10 22:18:20 +08:00
|
|
|
foreach (TableSetBase *ts, d->tableSets)
|
|
|
|
|
rowsAffected += ts->save(this, cleanUp);
|
2017-05-28 23:08:59 +08:00
|
|
|
return rowsAffected;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
void Database::cleanUp()
|
|
|
|
|
{
|
2017-09-10 22:18:20 +08:00
|
|
|
Q_D(Database);
|
|
|
|
|
foreach (TableSetBase *ts, d->tableSets)
|
2016-05-21 16:09:03 +08:00
|
|
|
ts->clearChilds();
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-01 18:01:21 +08:00
|
|
|
NUT_END_NAMESPACE
|