File indexing completed on 2024-05-12 17:24:09
0001 #include "database.h" 0002 0003 #include <QStandardPaths> 0004 #include <ThreadedDatabase> 0005 #include <QDir> 0006 #include <QStringBuilder> 0007 #include <QDateTime> 0008 #include <QCoroTask> 0009 #include <QCoroFuture> 0010 0011 using namespace DB; 0012 0013 HealthEvent::HealthEvent(int _health_date, int _health) 0014 : health_date(_health_date) 0015 , health(_health) 0016 {} 0017 0018 Database::Database() 0019 { 0020 const auto databaseDirectory = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); 0021 0022 // Make sure the database directory exists 0023 QDir(databaseDirectory).mkpath(QStringLiteral(".")); 0024 0025 DatabaseConfiguration config; 0026 config.setDatabaseName(databaseDirectory % QDir::separator() % "plants.sqlite"); 0027 config.setType(DatabaseType::SQLite); 0028 0029 m_database = ThreadedDatabase::establishConnection(config); 0030 m_database->runMigrations(":/contents/migrations/"); 0031 } 0032 0033 QCoro::Task<DB::Plant::Id> Database::addPlant(const QString &name, const QString &species, const QString &imgUrl, const int waterInterval, const QString location, const int dateOfBirth, const int lastWatered, const int healthDate, const int health) 0034 { 0035 auto id = co_await m_database->getResult<SingleValue<int>>("insert into plants (name, species, img_url, water_intervall, location, date_of_birth) values (?, ?, ?, ?, ?, ?) returning plant_id", name, species, imgUrl, waterInterval, location, dateOfBirth); 0036 0037 m_database->execute("insert into water_history (plant_id, water_date) values (?, ?)", id.value().value, lastWatered); 0038 m_database->execute("insert into health_history (plant_id, health_date, health) values (?, ?, ?)", id.value().value, healthDate, health); 0039 0040 co_return id.value().value; 0041 } 0042 0043 void Database::editPlant(const DB::Plant::Id plantId, const QString &name, const QString &species, const QString &imgUrl, const int waterIntervall, const QString location, const int dateOfBirth) 0044 { 0045 0046 auto future = m_database->getResult<SingleValue<int>>("update plants SET name = ?, species = ?, img_url = ?, water_intervall = ?, location = ?, date_of_birth = ? where plant_id = ?", name, species, imgUrl, waterIntervall, location, dateOfBirth, plantId); 0047 QCoro::connect(std::move(future), this, [=, this](auto) { 0048 Q_EMIT plantChanged(plantId); 0049 }); 0050 } 0051 0052 void Database::deletePlant(const DB::Plant::Id plantId) 0053 { 0054 auto future = m_database->execute("delete from plants where plant_id = ?", plantId); 0055 QCoro::connect(std::move(future), this, [=, this]() { 0056 m_database->execute("delete from water_history where plant_id = ?", plantId); 0057 m_database->execute("delete from health_history where plant_id = ?", plantId); 0058 Q_EMIT plantChanged(plantId); 0059 }); 0060 } 0061 QFuture<std::vector<Plant>> Database::plants() 0062 { 0063 return m_database->getResults<Plant>(R"( 0064 select 0065 plants.plant_id, name, species, img_url, water_intervall, location, date_of_birth, parent, max(water_date), max(health_date) as latest_health_date, health 0066 from 0067 plants 0068 left join 0069 water_history 0070 on 0071 plants.plant_id = water_history.plant_id 0072 left join 0073 health_history 0074 on 0075 plants.plant_id = health_history.plant_id 0076 group by 0077 plants.plant_id 0078 )" ); 0079 } 0080 0081 QFuture<std::optional<Plant>> Database::plant(int plant_id) 0082 { 0083 return m_database->getResult<Plant>(R"( 0084 select 0085 plants.plant_id, name, species, img_url, water_intervall, location, date_of_birth, parent, max(water_date), max(health_date) as latest_health_date, health 0086 from 0087 plants 0088 left join 0089 water_history 0090 on 0091 plants.plant_id = water_history.plant_id 0092 left join 0093 health_history 0094 on 0095 plants.plant_id = health_history.plant_id 0096 where plants.plant_id = ? 0097 group by 0098 plants.plant_id 0099 )", plant_id); 0100 } 0101 0102 QFuture<std::vector<SingleValue<int>>> Database::waterEvents(int plantId) 0103 { 0104 return m_database->getResults<SingleValue<int>>("select water_date from water_history where plant_id = ?", plantId); 0105 } 0106 0107 QFuture<std::vector<HealthEvent>> Database::healthEvents(int plantId) 0108 { 0109 return m_database->getResults<HealthEvent>("select health_date, health from health_history where plant_id = ?", plantId); 0110 } 0111 0112 void Database::waterPlant(const int plantId, const int waterDate) 0113 { 0114 m_database->execute("insert into water_history (plant_id, water_date) values (?, ?)", plantId, waterDate); 0115 Q_EMIT plantChanged(plantId); 0116 } 0117 0118 void Database::addHealthEvent(const int plantId, const int waterDate, const int health) 0119 { 0120 m_database->execute("insert into health_history (plant_id, health_date, health) values (?, ?, ?)", plantId, waterDate, health); 0121 Q_EMIT plantChanged(plantId); 0122 } 0123 0124 QFuture<std::optional<SingleValue<int>>> Database::getLastHealthDate(const int plantId) 0125 { 0126 return m_database->getResult<SingleValue<int>>("select health_date from health_history where plant_id = ? order by desc limit 1", plantId); 0127 0128 } 0129 0130 //void Database::replaceLastHealthEvent(const int plantId, const int waterDate, const int health) 0131 //{ 0132 // m_database->execute("insert into health_history (plant_id, health_date, health) values (?, ?, ?)", plantId, waterDate, health); 0133 //} 0134 0135 Database &Database::instance() 0136 { 0137 static Database inst; 0138 return inst; 0139 }