#ifndef PGCONTAINER_H #define PGCONTAINER_H #include "Pgsql_declare.h" #include "Pgsql_Result.h" #include #include #include #include class PgDatabaseCatalog; class IPgContainer { public: IPgContainer(PgDatabaseCatalog& cat); virtual ~IPgContainer() = default; virtual std::string getLoadQuery() const = 0; virtual void load(const Pgsql::Result &res) = 0; bool minimumVersion(int required_version) const; protected: PgDatabaseCatalog& m_catalog; }; template class PgContainer: public IPgContainer { public: using t_Container = std::vector; ///< Do not assume it will stay a vector only expect bidirectional access PgContainer() = default; explicit PgContainer(PgDatabaseCatalog& cat) : IPgContainer(cat) { } typename t_Container::const_iterator begin() const { return m_container.begin(); } typename t_Container::const_iterator end() const { return m_container.end(); } void clear() { m_container.clear(); } size_t count() const { return m_container.size(); } const T* getByKey(const K &key) const { auto lb_result = std::lower_bound(m_container.begin(), m_container.end(), key); if (lb_result != m_container.end() && *lb_result == key) return &*lb_result; return nullptr; } const T* getByName(const QString &name) const { auto find_res = std::find(m_container.begin(), m_container.end(), name); if (find_res != m_container.end()) return &*find_res; return nullptr; } /// Retrieve element by index /// /// This function throws when idx is out of range /// otherwise it always returns a valid object. const T& getByIdx(int idx) const { return m_container.at(idx); } /** Override to implement complete loading logic. * * Do not override this function if you only want to implement * the loading of a single element. Override loadElem instead. */ virtual void load(const Pgsql::Result &res) override { m_container.clear(); m_container.reserve(res.rows()); for (auto row : res) m_container.push_back(loadElem(row)); std::sort(m_container.begin(), m_container.end()); } // Meant for mocking during testing void add(const T &elem) { m_container.push_back(elem); std::sort(m_container.begin(), m_container.end()); } protected: t_Container m_container; /** Override the implementation for this function to implement loading of single row. * * When overriding this function there is no need to override load. */ virtual T loadElem(const Pgsql::Row &) = 0; }; template class PgSPtrContainer: public IPgContainer { public: using t_Elem = std::shared_ptr; using t_Container = std::vector; ///< Do not assume it will stay a vector only expect bidirectional access explicit PgSPtrContainer(std::weak_ptr cat) : m_catalog(cat) {} typename t_Container::const_iterator begin() const { return m_container.begin(); } typename t_Container::const_iterator end() const { return m_container.end(); } void clear() { m_container.clear(); } int count() const { return (int)m_container.size(); } const t_Elem getByKey(const K &key) const { auto lb_result = std::lower_bound(m_container.begin(), m_container.end(), key); if (lb_result != m_container.end() && **lb_result == key) return *lb_result; return nullptr; } const t_Elem getByName(const QString name) const { auto find_res = std::find_if(m_container.begin(), m_container.end(), [name](auto e) -> bool { return *e = name; } ); if (find_res != m_container.end()) return *find_res; return nullptr; } const t_Elem getByIdx(int idx) const { return m_container.at(idx); } /** Override to implement complete loading logic. * * Do not override this function if you only want to implement * the loading of a single element. Override loadElem instead. */ virtual void load(const Pgsql::Result &res) override { m_container.clear(); m_container.reserve(res.rows()); for (auto row : res) m_container.push_back(loadElem(row)); std::sort(m_container.begin(), m_container.end()); } protected: std::weak_ptr m_catalog; t_Container m_container; /** Override the implementation for this function to implement loading of single row. * * When overriding this function there is no need to override load. */ virtual t_Elem loadElem(const Pgsql::Row &) = 0; private: }; #endif // PGCONTAINER_H