diff options
author | haslersn <sebastian.hasler@gmx.net> | 2019-07-03 01:59:50 +0200 |
---|---|---|
committer | haslersn <sebastian.hasler@gmx.net> | 2019-07-08 00:39:01 +0200 |
commit | ca1c35317a6da26b8903e4db450ba213746fa4a8 (patch) | |
tree | d325c6f0fbc71c2dfd63db05873635ebbbf21272 /src/djinterop/enginelibrary/el_crate_impl.cpp | |
parent | d246cfdb8e7bc75761c7972b4e1203bdbc6ca44b (diff) |
treewide: Make database/crate/track polymorphic
NOTE: The pimpl is polymorphic. This way, the user facing objects
can still be passed by value.
Diffstat (limited to 'src/djinterop/enginelibrary/el_crate_impl.cpp')
-rw-r--r-- | src/djinterop/enginelibrary/el_crate_impl.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/djinterop/enginelibrary/el_crate_impl.cpp b/src/djinterop/enginelibrary/el_crate_impl.cpp new file mode 100644 index 0000000..4ea8934 --- /dev/null +++ b/src/djinterop/enginelibrary/el_crate_impl.cpp @@ -0,0 +1,237 @@ +#include <sqlite_modern_cpp.h> + +#include <djinterop/djinterop.hpp> +#include <djinterop/enginelibrary/el_crate_impl.hpp> +#include <djinterop/enginelibrary/el_database_impl.hpp> +#include <djinterop/enginelibrary/el_storage.hpp> +#include <djinterop/enginelibrary/el_track_impl.hpp> + +namespace djinterop +{ +namespace enginelibrary +{ +using djinterop::crate; +using djinterop::track; + +namespace +{ +void update_path( + sqlite::database& music_db, crate cr, const std::string& parent_path) +{ + // update path + std::string path = parent_path + cr.name() + ';'; + music_db << "UPDATE Crate SET path = ? WHERE id = ?" << path << cr.id(); + + // recursive call in order to update the path of indirect descendants + for (crate cr2 : cr.children()) + { + update_path(music_db, cr2, path); + } +} + +} // namespace + +el_crate_impl::el_crate_impl(std::shared_ptr<el_storage> storage, int64_t id) + : crate_impl{id}, storage_{std::move(storage)} +{ +} + +void el_crate_impl::add_track(track tr) +{ + storage_->music_db << "BEGIN"; + + storage_->music_db + << "DELETE FROM CrateTrackList WHERE crateId = ? AND trackId = ?" + << id() << tr.id(); + + storage_->music_db + << "INSERT INTO CrateTrackList (crateId, trackId) VALUES (?, ?)" << id() + << tr.id(); + + storage_->music_db << "COMMIT"; +} + +std::vector<crate> el_crate_impl::children() +{ + std::vector<crate> results; + storage_->music_db + << "SELECT crateIdChild FROM CrateHierarchy WHERE crateId = ?" + << id() >> + [&](int64_t crate_id_child) { + results.emplace_back( + std::make_shared<el_crate_impl>(storage_, crate_id_child)); + }; + return results; +} + +void el_crate_impl::clear_tracks() +{ + storage_->music_db << "DELETE FROM CrateTrackList WHERE crateId = ?" + << id(); +} + +database el_crate_impl::db() +{ + return database{std::make_shared<el_database_impl>(storage_)}; +} + +std::vector<crate> el_crate_impl::descendants() +{ + std::vector<crate> results; + storage_->music_db + << "SELECT crateOriginId FROM CrateParentList WHERE crateParentId " + "= ? AND crateOriginId <> crateParentId" + << id() >> + [&](int64_t descendant_id) { + results.push_back(crate{ + std::make_shared<el_crate_impl>(storage_, descendant_id)}); + }; + return results; +} + +bool el_crate_impl::is_valid() +{ + bool valid = false; + storage_->music_db << "SELECT COUNT(*) FROM Crate WHERE id = ?" << id() >> + [&](int count) { + if (count == 1) + { + valid = true; + } + else if (count > 1) + { + throw crate_database_inconsistency{ + "More than one crate with the same ID", id()}; + } + }; + return valid; +} + +std::string el_crate_impl::name() +{ + boost::optional<std::string> name; + storage_->music_db << "SELECT title FROM Crate WHERE id = ?" << id() >> + [&](std::string title) { + if (!name) + { + name = std::move(title); + } + else + { + throw crate_database_inconsistency{ + "More than one crate with the same ID", id()}; + } + }; + if (!name) + { + throw crate_deleted{id()}; + } + return *name; +} + +boost::optional<crate> el_crate_impl::parent() +{ + boost::optional<crate> parent; + storage_->music_db + << "SELECT crateParentId FROM CrateParentList WHERE crateOriginId " + "= ? AND crateParentId <> crateOriginId" + << id() >> + [&](int64_t parent_id) { + if (!parent) + { + parent = + crate{std::make_shared<el_crate_impl>(storage_, parent_id)}; + } + else + { + throw crate_database_inconsistency{ + "More than one parent crate for the same crate", id()}; + } + }; + return parent; +} + +void el_crate_impl::remove_track(track tr) +{ + storage_->music_db + << "DELETE FROM CrateTrackList WHERE crateId = ? AND trackId = ?" + << id() << tr.id(); +} + +void el_crate_impl::set_name(boost::string_view name) +{ + storage_->music_db << "BEGIN"; + + // obtain parent's `path` + std::string parent_path; + storage_->music_db + << "SELECT path FROM Crate c JOIN CrateParentList cpl ON c.id = " + "cpl.crateParentId WHERE cpl.crateOriginId = ? AND " + "cpl.crateOriginId <> cpl.crateParentId" + << id() >> + [&](std::string path) { + if (parent_path.empty()) + { + parent_path = std::move(path); + } + else + { + throw crate_database_inconsistency{ + "More than one parent crate for the same crate", id()}; + } + }; + + // update name and path + std::string path = std::move(parent_path) + name.data() + ';'; + storage_->music_db << "UPDATE Crate SET title = ?, path = ? WHERE id = ?" + << name.data() << path << id(); + + // call the lambda in order to update the path of direct children + for (crate cr : children()) + { + update_path(storage_->music_db, cr, path); + } + + storage_->music_db << "COMMIT"; +} + +void el_crate_impl::set_parent(boost::optional<crate> parent) +{ + storage_->music_db << "BEGIN"; + + storage_->music_db << "DELETE FROM CrateParentList WHERE crateOriginId = ?" + << id(); + + storage_->music_db << "INSERT INTO CrateParentList (crateOriginId, " + "crateParentId) VALUES (?, ?)" + << id() << (parent ? parent->id() : id()); + + storage_->music_db << "DELETE FROM CrateHierarchy WHERE crateIdChild = ?" + << id(); + + if (parent) + { + storage_->music_db + << "INSERT INTO CrateHierarchy (crateId, crateIdChild) SELECT " + "crateId, ? FROM CrateHierarchy WHERE crateIdChild = ? UNION " + "SELECT ? AS crateId, ? AS crateIdChild" + << id() << parent->id() << parent->id() << id(); + } + + storage_->music_db << "COMMIT"; +} + +std::vector<track> el_crate_impl::tracks() +{ + std::vector<track> results; + storage_->music_db << "SELECT trackId FROM CrateTrackList WHERE crateId = ?" + << id() >> + [&](int64_t track_id) { + results.emplace_back( + std::make_shared<el_track_impl>(storage_, track_id)); + }; + return results; +} + +} // namespace enginelibrary +} // namespace djinterop
\ No newline at end of file |