diff options
Diffstat (limited to 'xbmc/dbwrappers/Database.h')
-rw-r--r-- | xbmc/dbwrappers/Database.h | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/xbmc/dbwrappers/Database.h b/xbmc/dbwrappers/Database.h new file mode 100644 index 0000000..2f3d35d --- /dev/null +++ b/xbmc/dbwrappers/Database.h @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +namespace dbiplus +{ +class Database; +class Dataset; +} // namespace dbiplus + +#include <memory> +#include <string> +#include <vector> + +class DatabaseSettings; // forward +class CDbUrl; +class CProfileManager; +struct SortDescription; + +class CDatabase +{ +public: + class Filter + { + public: + Filter() : fields("*") {} + explicit Filter(const char* w) : fields("*"), where(w) {} + explicit Filter(const std::string& w) : fields("*"), where(w) {} + + void AppendField(const std::string& strField); + void AppendJoin(const std::string& strJoin); + void AppendWhere(const std::string& strWhere, bool combineWithAnd = true); + void AppendOrder(const std::string& strOrder); + void AppendGroup(const std::string& strGroup); + + std::string fields; + std::string join; + std::string where; + std::string order; + std::string group; + std::string limit; + }; + + struct DatasetFieldInfo + { + DatasetFieldInfo(bool fetch, bool output, int recno) + : fetch(fetch), output(output), recno(recno) + { + } + + bool fetch; + bool output; + int recno; + std::string strField; + }; + + class DatasetLayout + { + public: + DatasetLayout(size_t totalfields); + void SetField(int fieldNo, const std::string& strField, bool bOutput = false); + void AdjustRecordNumbers(int offset); + bool GetFetch(int fieldno); + void SetFetch(int fieldno, bool bFetch = true); + bool GetOutput(int fieldno); + int GetRecNo(int fieldno); + const std::string GetFields(); + bool HasFilterFields(); + + private: + std::vector<DatasetFieldInfo> m_fields; + }; + + class ExistsSubQuery + { + public: + explicit ExistsSubQuery(const std::string& table) : tablename(table) {} + ExistsSubQuery(const std::string& table, const std::string& parameter) + : tablename(table), param(parameter) + { + } + void AppendJoin(const std::string& strJoin); + void AppendWhere(const std::string& strWhere, bool combineWithAnd = true); + bool BuildSQL(std::string& strSQL); + + std::string tablename; + std::string param; + std::string join; + std::string where; + }; + + CDatabase(); + virtual ~CDatabase(void); + bool IsOpen(); + virtual void Close(); + bool Compress(bool bForce = true); + void Interrupt(); + + bool Open(const DatabaseSettings& db); + + void BeginTransaction(); + virtual bool CommitTransaction(); + void RollbackTransaction(); + void CopyDB(const std::string& latestDb); + void DropAnalytics(); + + std::string PrepareSQL(std::string strStmt, ...) const; + + /*! + * @brief Get a single value from a table. + * @remarks The values of the strWhereClause and strOrderBy parameters have to be FormatSQL'ed when used. + * @param strTable The table to get the value from. + * @param strColumn The column to get. + * @param strWhereClause If set, use this WHERE clause. + * @param strOrderBy If set, use this ORDER BY clause. + * @return The requested value or an empty string if it wasn't found. + */ + std::string GetSingleValue(const std::string& strTable, + const std::string& strColumn, + const std::string& strWhereClause = std::string(), + const std::string& strOrderBy = std::string()); + std::string GetSingleValue(const std::string& query); + + /*! \brief Get a single value from a query on a dataset. + \param query the query in question. + \param ds the dataset to use for the query. + \return the value from the query, empty on failure. + */ + std::string GetSingleValue(const std::string& query, std::unique_ptr<dbiplus::Dataset>& ds); + + /*! + * @brief Get a single integer value from a table. + * @remarks The values of the strWhereClause and strOrderBy parameters have to be FormatSQL'ed when used. + * @param strTable The table to get the value from. + * @param strColumn The column to get. + * @param strWhereClause If set, use this WHERE clause. + * @param strOrderBy If set, use this ORDER BY clause. + * @return The requested value or 0 if it wasn't found. + */ + int GetSingleValueInt(const std::string& strTable, + const std::string& strColumn, + const std::string& strWhereClause = std::string(), + const std::string& strOrderBy = std::string()); + int GetSingleValueInt(const std::string& query); + + /*! \brief Get a single integer value from a query on a dataset. + \param query the query in question. + \param ds the dataset to use for the query. + \return the value from the query, 0 on failure. + */ + int GetSingleValueInt(const std::string& query, std::unique_ptr<dbiplus::Dataset>& ds); + + /*! + * @brief Delete values from a table. + * @param strTable The table to delete the values from. + * @param filter The Filter to apply to this query. + * @return True if the query was executed successfully, false otherwise. + */ + bool DeleteValues(const std::string& strTable, const Filter& filter = Filter()); + + /*! + * @brief Execute a query that does not return any result. + * Note that if BeginMultipleExecute() has been called, the + * query will be queued until CommitMultipleExecute() is called. + * @param strQuery The query to execute. + * @return True if the query was executed successfully, false otherwise. + * @sa BeginMultipleExecute, CommitMultipleExecute + */ + bool ExecuteQuery(const std::string& strQuery); + + /*! + * @brief Execute a query that returns a result. + * @remarks Call m_pDS->close(); to clean up the dataset when done. + * @param strQuery The query to execute. + * @return True if the query was executed successfully, false otherwise. + */ + bool ResultQuery(const std::string& strQuery) const; + + /*! + * @brief Start a multiple execution queue. Any ExecuteQuery() function + * following this call will be queued rather than executed until + * CommitMultipleExecute() is performed. + * NOTE: Queries that rely on any queued execute query will not + * function as expected during this period! + * @return true if we could start a multiple execution queue, false otherwise. + * @sa CommitMultipleExecute, ExecuteQuery + */ + bool BeginMultipleExecute(); + + /*! + * @brief Commit the multiple execution queue to the database. + * Queries are performed within a transaction, and the transaction + * is rolled back should any one query fail. + * @return True if the queries were executed successfully, false otherwise. + * @sa BeginMultipleExecute, ExecuteQuery + */ + bool CommitMultipleExecute(); + + /*! + * @brief Put an INSERT or REPLACE query in the queue. + * @param strQuery The query to queue. + * @return True if the query was added successfully, false otherwise. + */ + bool QueueInsertQuery(const std::string& strQuery); + + /*! + * @brief Commit all queries in the queue. + * @return True if all queries were executed successfully, false otherwise. + */ + bool CommitInsertQueries(); + + /*! + * @brief Get the number of INSERT queries in the queue. + * @return The number of queries. + */ + size_t GetInsertQueriesCount(); + + /*! + * @brief Put a DELETE query in the queue. + * @param strQuery The query to queue. + * @return True if the query was added successfully, false otherwise. + */ + bool QueueDeleteQuery(const std::string& strQuery); + + /*! + * @brief Commit all queued DELETE queries. + * @return True if all queries were executed successfully, false otherwise. + */ + bool CommitDeleteQueries(); + + /*! + * @brief Get the number of DELETE queries in the queue. + * @return The number of queries. + */ + size_t GetDeleteQueriesCount(); + + virtual bool GetFilter(CDbUrl& dbUrl, Filter& filter, SortDescription& sorting) { return true; } + virtual bool BuildSQL(const std::string& strBaseDir, + const std::string& strQuery, + Filter& filter, + std::string& strSQL, + CDbUrl& dbUrl); + virtual bool BuildSQL(const std::string& strBaseDir, + const std::string& strQuery, + Filter& filter, + std::string& strSQL, + CDbUrl& dbUrl, + SortDescription& sorting); + + bool Connect(const std::string& dbName, const DatabaseSettings& db, bool create); + +protected: + friend class CDatabaseManager; + + void Split(const std::string& strFileNameAndPath, std::string& strPath, std::string& strFileName); + + virtual bool Open(); + + /*! \brief Create database tables and analytics as needed. + Calls CreateTables() and CreateAnalytics() on child classes. + */ + bool CreateDatabase(); + + /* \brief Create tables for the current database schema. + Will be called on database creation. + */ + virtual void CreateTables() = 0; + + /* \brief Create views, indices and triggers for the current database schema. + Will be called on database creation and database update. + */ + virtual void CreateAnalytics() = 0; + + /* \brief Update database tables to the current version. + Note that analytics (views, indices, triggers) are not present during this + function, so don't rely on them. + */ + virtual void UpdateTables(int version) {} + + /* \brief The minimum schema version that we support updating from. + */ + virtual int GetMinSchemaVersion() const { return 0; } + + /* \brief The current schema version. + */ + virtual int GetSchemaVersion() const = 0; + virtual const char* GetBaseDBName() const = 0; + + int GetDBVersion(); + + bool BuildSQL(const std::string& strQuery, const Filter& filter, std::string& strSQL); + + bool m_sqlite; ///< \brief whether we use sqlite (defaults to true) + + std::unique_ptr<dbiplus::Database> m_pDB; + std::unique_ptr<dbiplus::Dataset> m_pDS; + std::unique_ptr<dbiplus::Dataset> m_pDS2; + +protected: + // Construction parameters + const CProfileManager& m_profileManager; + +private: + void InitSettings(DatabaseSettings& dbSettings); + void UpdateVersionNumber(); + + bool m_bMultiInsert = + false; /*!< True if there are any queries in the insert queue, false otherwise */ + bool m_bMultiDelete = + false; /*!< True if there are any queries in the delete queue, false otherwise */ + unsigned int m_openCount; + + bool m_multipleExecute; + std::vector<std::string> m_multipleQueries; +}; |