Files
yourpart3/src/database.cpp

120 lines
3.5 KiB
C++

#include "database.h"
#include <pqxx/pqxx>
#include <vector>
#include <unordered_map>
#include <string>
#include <iostream>
Database::Database(const std::string &conninfo)
{
try {
connection_ = std::make_unique<pqxx::connection>(conninfo);
if (!connection_->is_open()) {
throw std::runtime_error("Konnte DB-Verbindung nicht öffnen!");
}
} catch (const std::exception &e) {
std::cerr << "[Database] Fehler beim Verbinden: " << e.what() << std::endl;
throw;
}
}
std::vector<std::map<std::string, std::string>>
Database::query(const std::string &sql)
{
std::vector<std::map<std::string, std::string>> rows;
try {
pqxx::work txn(*connection_);
pqxx::result r = txn.exec(sql);
txn.commit();
for (auto row : r) {
std::map<std::string, std::string> oneRow;
for (auto f = 0u; f < row.size(); f++) {
std::string colName = r.column_name(f);
std::string value = row[f].c_str() ? row[f].c_str() : "";
oneRow[colName] = value;
}
rows.push_back(std::move(oneRow));
}
} catch (const std::exception &ex) {
std::cerr << "[Database] query-Fehler: " << ex.what() << "\nSQL: " << sql << std::endl;
}
return rows;
}
void Database::prepare(const std::string &stmtName, const std::string &sql)
{
try {
// Versuche zuerst, das alte Statement zu entfernen, falls es existiert
try {
remove(stmtName);
} catch (...) {
// Ignoriere Fehler beim Entfernen - das Statement existiert möglicherweise nicht
}
// Erstelle das neue Statement
pqxx::work txn(*connection_);
txn.conn().prepare(stmtName, sql);
txn.commit();
} catch (const std::exception &ex) {
std::cerr << "[Database] prepare-Fehler: " << ex.what()
<< "\nSQL: " << sql << std::endl;
}
}
Database::FieldList Database::execute(const std::string& stmtName,
const std::vector<std::string>& params)
{
try {
pqxx::work txn(*connection_);
pqxx::result res;
if (params.empty()) {
res = txn.exec_prepared(stmtName);
} else {
pqxx::params p;
for (const auto& v : params) p.append(v);
res = txn.exec_prepared(stmtName, p);
}
FieldList out;
out.reserve(res.size());
for (const auto& row : res) {
std::unordered_map<std::string, std::string> m;
for (const auto& f : row) {
m.emplace(f.name(), f.is_null() ? std::string{} : std::string(f.c_str()));
}
out.emplace_back(std::move(m));
}
txn.commit();
return out;
} catch (const std::exception& e) {
std::cerr << "[Database] execute-Fehler: " << e.what()
<< "\n\nStatement: " << stmtName << std::endl;
return {};
}
}
void Database::remove(const std::string &stmtName) {
pqxx::work txn(*connection_);
txn.conn().unprepare(stmtName);
txn.commit();
}
bool Database::isValid() const {
try {
if (!connection_ || !connection_->is_open()) {
return false;
}
pqxx::work txn(*connection_);
txn.exec("SELECT 1"); // Einfacher Ping
txn.commit();
return true;
} catch (const std::exception &ex) {
std::cerr << "[Database] Verbindung ungültig: " << ex.what() << "\n";
return false;
}
}