#include #include #include #include #include #include #include #include #ifdef _WIN32 #include #endif // not in header because of linking static QString _rootPath; static QThreadStorage _databasePool; DBManager::DBManager(QObject* parent) : QObject(parent) , _log(Logger::getInstance("DB")) , _readonlyMode (false) { } DBManager::~DBManager() { } void DBManager::setRootPath(const QString& rootPath) { _rootPath = rootPath; // create directory QDir().mkpath(_rootPath+"/db"); } void DBManager::setTable(const QString& table) { _table = table; } QSqlDatabase DBManager::getDB() const { if(_databasePool.hasLocalData()) return _databasePool.localData(); else { auto db = QSqlDatabase::addDatabase("QSQLITE", QUuid::createUuid().toString()); _databasePool.setLocalData(db); db.setDatabaseName(_rootPath+"/db/"+_dbn+".db"); if(!db.open()) { Error(_log, QSTRING_CSTR(db.lastError().text())); throw std::runtime_error("Failed to open database connection!"); } return db; } } bool DBManager::createRecord(const VectorPair& conditions, const QVariantMap& columns) const { if ( _readonlyMode ) { return false; } if(recordExists(conditions)) { // if there is no column data, return if(columns.isEmpty()) return true; if(!updateRecord(conditions, columns)) return false; return true; } QSqlDatabase idb = getDB(); QSqlQuery query(idb); query.setForwardOnly(true); QVariantList cValues; QStringList prep; QStringList placeh; // prep merge columns & condition QVariantMap::const_iterator i = columns.constBegin(); while (i != columns.constEnd()) { prep.append(i.key()); cValues += i.value(); placeh.append("?"); ++i; } for(const auto& pair : conditions) { // remove the condition statements QString tmp = pair.first; prep << tmp.remove("AND"); cValues << pair.second; placeh.append("?"); } query.prepare(QString("INSERT INTO %1 ( %2 ) VALUES ( %3 )").arg(_table,prep.join(", ")).arg(placeh.join(", "))); // add column & condition values doAddBindValue(query, cValues); if(!query.exec()) { Error(_log, "Failed to create record: '%s' in table: '%s' Error: %s", QSTRING_CSTR(prep.join(", ")), QSTRING_CSTR(_table), QSTRING_CSTR(idb.lastError().text())); return false; } return true; } bool DBManager::recordExists(const VectorPair& conditions) const { if(conditions.isEmpty()) return false; QSqlDatabase idb = getDB(); QSqlQuery query(idb); query.setForwardOnly(true); QStringList prepCond; QVariantList bindVal; prepCond << "WHERE"; for(const auto& pair : conditions) { prepCond << pair.first+"=?"; bindVal << pair.second; } query.prepare(QString("SELECT * FROM %1 %2").arg(_table,prepCond.join(" "))); doAddBindValue(query, bindVal); if(!query.exec()) { Error(_log, "Failed recordExists(): '%s' in table: '%s' Error: %s", QSTRING_CSTR(prepCond.join(" ")), QSTRING_CSTR(_table), QSTRING_CSTR(idb.lastError().text())); return false; } int entry = 0; while (query.next()) { entry++; } if(entry) return true; return false; } bool DBManager::updateRecord(const VectorPair& conditions, const QVariantMap& columns) const { if ( _readonlyMode ) { return false; } QSqlDatabase idb = getDB(); QSqlQuery query(idb); query.setForwardOnly(true); QVariantList values; QStringList prep; // prepare columns valus QVariantMap::const_iterator i = columns.constBegin(); while (i != columns.constEnd()) { prep += i.key()+"=?"; values += i.value(); ++i; } // prepare condition values QStringList prepCond; QVariantList prepBindVal; if(!conditions.isEmpty()) prepCond << "WHERE"; for(const auto& pair : conditions) { prepCond << pair.first+"=?"; prepBindVal << pair.second; } query.prepare(QString("UPDATE %1 SET %2 %3").arg(_table,prep.join(", ")).arg(prepCond.join(" "))); // add column values doAddBindValue(query, values); // add condition values doAddBindValue(query, prepBindVal); if(!query.exec()) { Error(_log, "Failed to update record: '%s' in table: '%s' Error: %s", QSTRING_CSTR(prepCond.join(" ")), QSTRING_CSTR(_table), QSTRING_CSTR(idb.lastError().text())); return false; } return true; } bool DBManager::getRecord(const VectorPair& conditions, QVariantMap& results, const QStringList& tColumns, const QStringList& tOrder) const { QSqlDatabase idb = getDB(); QSqlQuery query(idb); query.setForwardOnly(true); QString sColumns("*"); if(!tColumns.isEmpty()) sColumns = tColumns.join(", "); QString sOrder(""); if(!tOrder.isEmpty()) { sOrder = " ORDER BY "; sOrder.append(tOrder.join(", ")); } // prep conditions QStringList prepCond; QVariantList bindVal; if(!conditions.isEmpty()) prepCond << " WHERE"; for(const auto& pair : conditions) { prepCond << pair.first+"=?"; bindVal << pair.second; } query.prepare(QString("SELECT %1 FROM %2%3%4").arg(sColumns,_table).arg(prepCond.join(" ")).arg(sOrder)); doAddBindValue(query, bindVal); if(!query.exec()) { Error(_log, "Failed to get record: '%s' in table: '%s' Error: %s", QSTRING_CSTR(prepCond.join(" ")), QSTRING_CSTR(_table), QSTRING_CSTR(idb.lastError().text())); return false; } // go to first row query.next(); QSqlRecord rec = query.record(); for(int i = 0; i& results, const QStringList& tColumns, const QStringList& tOrder) const { QSqlDatabase idb = getDB(); QSqlQuery query(idb); query.setForwardOnly(true); QString sColumns("*"); if(!tColumns.isEmpty()) sColumns = tColumns.join(", "); QString sOrder(""); if(!tOrder.isEmpty()) { sOrder = " ORDER BY "; sOrder.append(tOrder.join(", ")); } query.prepare(QString("SELECT %1 FROM %2%3").arg(sColumns,_table,sOrder)); if(!query.exec()) { Error(_log, "Failed to get records: '%s' in table: '%s' Error: %s", QSTRING_CSTR(sColumns), QSTRING_CSTR(_table), QSTRING_CSTR(idb.lastError().text())); return false; } // iterate through all found records while(query.next()) { QVariantMap entry; QSqlRecord rec = query.record(); for(int i = 0; i