diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-05-16 14:11:38 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-05-16 14:11:38 +1000 |
| commit | d71f726c42963d55809605b4dc4144970ca0f230 (patch) | |
| tree | 5dc8e6355f5e870e767c3d23ec4009bc39155821 /src/database/include | |
| parent | 785349eb5b3255d0a51ca7459531f75cb47c90ac (diff) | |
| download | tangara-fw-d71f726c42963d55809605b4dc4144970ca0f230.tar.gz | |
Add pagination to database queries
Diffstat (limited to 'src/database/include')
| -rw-r--r-- | src/database/include/database.hpp | 81 | ||||
| -rw-r--r-- | src/database/include/song.hpp | 11 |
2 files changed, 43 insertions, 49 deletions
diff --git a/src/database/include/database.hpp b/src/database/include/database.hpp index 29872e8d..da0ed083 100644 --- a/src/database/include/database.hpp +++ b/src/database/include/database.hpp @@ -22,7 +22,15 @@ namespace database { -typedef std::unique_ptr<leveldb::Iterator> Continuation; +template <typename T> +struct Continuation { + std::shared_ptr<std::unique_ptr<leveldb::Iterator>> iterator; + std::string prefix; + std::string start_key; + bool forward; + bool was_prev_forward; + size_t page_size; +}; /* * Wrapper for a set of results from the database. Owns the list of results, as @@ -32,29 +40,23 @@ typedef std::unique_ptr<leveldb::Iterator> Continuation; template <typename T> class Result { public: - auto values() -> std::vector<T>* { return values_.release(); } - auto continuation() -> Continuation { return std::move(c_); } - auto HasMore() -> bool { return c_->Valid(); } - - Result(std::vector<T>* values, Continuation c) - : values_(values), c_(std::move(c)) {} - - Result(std::unique_ptr<std::vector<T>> values, Continuation c) - : values_(std::move(values)), c_(std::move(c)) {} + auto values() const -> const std::vector<T>& { return values_; } - Result(Result&& other) - : values_(move(other.values_)), c_(std::move(other.c_)) {} + auto next_page() -> std::optional<Continuation<T>>& { return next_page_; } + auto prev_page() -> std::optional<Continuation<T>>& { return prev_page_; } - Result operator=(Result&& other) { - return Result(other.values(), std::move(other.continuation())); - } + Result(const std::vector<T>&& values, + std::optional<Continuation<T>> next, + std::optional<Continuation<T>> prev) + : values_(values), next_page_(next), prev_page_(prev) {} Result(const Result&) = delete; Result& operator=(const Result&) = delete; private: - std::unique_ptr<std::vector<T>> values_; - Continuation c_; + std::vector<T> values_; + std::optional<Continuation<T>> next_page_; + std::optional<Continuation<T>> prev_page_; }; class Database { @@ -73,13 +75,11 @@ class Database { auto Update() -> std::future<void>; - auto GetSongs(std::size_t page_size) -> std::future<Result<Song>>; - auto GetMoreSongs(std::size_t page_size, Continuation c) - -> std::future<Result<Song>>; + auto GetSongs(std::size_t page_size) -> std::future<Result<Song>*>; + auto GetDump(std::size_t page_size) -> std::future<Result<std::string>*>; - auto GetDump(std::size_t page_size) -> std::future<Result<std::string>>; - auto GetMoreDump(std::size_t page_size, Continuation c) - -> std::future<Result<std::string>>; + template <typename T> + auto GetPage(Continuation<T>* c) -> std::future<Result<T>*>; Database(const Database&) = delete; Database& operator=(const Database&) = delete; @@ -110,31 +110,20 @@ class Database { -> void; template <typename T> - using Parser = std::function<std::optional<T>(const leveldb::Slice& key, - const leveldb::Slice& value)>; - - template <typename T> - auto Query(const leveldb::Slice& prefix, - std::size_t max_results, - Parser<T> parser) -> Result<T> { - leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions()); - it->Seek(prefix); - return Query(it, max_results, parser); - } + auto dbGetPage(const Continuation<T>& c) -> Result<T>*; template <typename T> - auto Query(leveldb::Iterator* it, std::size_t max_results, Parser<T> parser) - -> Result<T> { - auto results = std::make_unique<std::vector<T>>(); - for (std::size_t i = 0; i < max_results && it->Valid(); i++) { - std::optional<T> r = std::invoke(parser, it->key(), it->value()); - if (r) { - results->push_back(*r); - } - it->Next(); - } - return {std::move(results), std::unique_ptr<leveldb::Iterator>(it)}; - } + auto ParseRecord(const leveldb::Slice& key, const leveldb::Slice& val) + -> std::optional<T>; }; +template <> +auto Database::ParseRecord<Song>(const leveldb::Slice& key, + const leveldb::Slice& val) + -> std::optional<Song>; +template <> +auto Database::ParseRecord<std::string>(const leveldb::Slice& key, + const leveldb::Slice& val) + -> std::optional<std::string>; + } // namespace database diff --git a/src/database/include/song.hpp b/src/database/include/song.hpp index e51e5587..9a84e124 100644 --- a/src/database/include/song.hpp +++ b/src/database/include/song.hpp @@ -4,6 +4,7 @@ #include <optional> #include <string> +#include <utility> #include "leveldb/db.h" #include "span.hpp" @@ -133,16 +134,20 @@ class SongData { */ class Song { public: - Song(SongData data, SongTags tags) : data_(data), tags_(tags) {} + Song(const SongData& data, const SongTags& tags) : data_(data), tags_(tags) {} + Song(const Song& other) = default; - auto data() -> const SongData& { return data_; } - auto tags() -> const SongTags& { return tags_; } + auto data() const -> const SongData& { return data_; } + auto tags() const -> const SongTags& { return tags_; } bool operator==(const Song&) const = default; + Song operator=(const Song& other) const { return Song(other); } private: const SongData data_; const SongTags tags_; }; +void swap(Song& first, Song& second); + } // namespace database |
