LCOV - code coverage report
Current view: top level - libgnucash/backend/sql - gnc-sql-backend.hpp (source / functions) Hit Total Coverage
Test: gnucash.info Lines: 6 7 85.7 %
Date: 2024-10-31 11:06:40 Functions: 6 7 85.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***********************************************************************\
       2                 :            :  * gnc-sql-backend.hpp: Qof Backend for SQL Databases                  *
       3                 :            :  *                                                                     *
       4                 :            :  * Copyright 2016 John Ralls <jralls@ceridwen.us>                      *
       5                 :            :  *                                                                     *
       6                 :            :  * This program is free software; you can redistribute it and/or       *
       7                 :            :  * modify it under the terms of the GNU General Public License as      *
       8                 :            :  * published by the Free Software Foundation; either version 2 of      *
       9                 :            :  * the License, or (at your option) any later version.                 *
      10                 :            :  *                                                                     *
      11                 :            :  * This program is distributed in the hope that it will be useful,     *
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of      *
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
      14                 :            :  * GNU General Public License for more details.                        *
      15                 :            :  *                                                                     *
      16                 :            :  * You should have received a copy of the GNU General Public License   *
      17                 :            :  * along with this program; if not, contact:                           *
      18                 :            :  *                                                                     *
      19                 :            :  * Free Software Foundation           Voice:  +1-617-542-5942          *
      20                 :            :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652          *
      21                 :            :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                      *
      22                 :            : \***********************************************************************/
      23                 :            : 
      24                 :            : #ifndef __GNC_SQL_BACKEND_HPP__
      25                 :            : #define __GNC_SQL_BACKEND_HPP__
      26                 :            : 
      27                 :            : #include <qof.h>
      28                 :            : #include <Account.h>
      29                 :            : 
      30                 :            : #include <memory>
      31                 :            : #include <exception>
      32                 :            : #include <sstream>
      33                 :            : #include <vector>
      34                 :            : #include <qof-backend.hpp>
      35                 :            : 
      36                 :            : class GncSqlColumnTableEntry;
      37                 :            : using GncSqlColumnTableEntryPtr = std::shared_ptr<GncSqlColumnTableEntry>;
      38                 :            : using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
      39                 :            : class GncSqlObjectBackend;
      40                 :            : using GncSqlObjectBackendPtr = std::shared_ptr<GncSqlObjectBackend>;
      41                 :            : using OBEEntry = std::tuple<std::string, GncSqlObjectBackendPtr>;
      42                 :            : using OBEVec = std::vector<OBEEntry>;
      43                 :            : class GncSqlConnection;
      44                 :            : class GncSqlStatement;
      45                 :            : using GncSqlStatementPtr = std::unique_ptr<GncSqlStatement>;
      46                 :            : class GncSqlResult;
      47                 :            : using GncSqlResultPtr = GncSqlResult*;
      48                 :            : using VersionPair = std::pair<const std::string, unsigned int>;
      49                 :            : using VersionVec = std::vector<VersionPair>;
      50                 :            : using uint_t = unsigned int;
      51                 :            : 
      52                 :            : typedef enum
      53                 :            : {
      54                 :            :     OP_DB_INSERT,
      55                 :            :     OP_DB_UPDATE,
      56                 :            :     OP_DB_DELETE
      57                 :            : } E_DB_OPERATION;
      58                 :            : 
      59                 :            : /**
      60                 :            :  *
      61                 :            :  * Main SQL backend structure.
      62                 :            :  */
      63                 :            : class GncSqlBackend : public QofBackend
      64                 :            : {
      65                 :            : public:
      66                 :            :     GncSqlBackend(GncSqlConnection *conn, QofBook* book);
      67                 :            :     virtual ~GncSqlBackend();
      68                 :            :     /**
      69                 :            :      * Load the contents of an SQL database into a book.
      70                 :            :      *
      71                 :            :      * @param book Book to be loaded
      72                 :            :      */
      73                 :            :     void load(QofBook*, QofBackendLoadType) override;
      74                 :            :     /**
      75                 :            :      * Save the contents of a book to an SQL database.
      76                 :            :      *
      77                 :            :      * @param book Book to be saved
      78                 :            :      */
      79                 :            :     void sync(QofBook*) override;
      80                 :            :     /**
      81                 :            :      * An object is about to be edited.
      82                 :            :      *
      83                 :            :      * @param inst Object being edited
      84                 :            :      */
      85                 :            :     void begin(QofInstance*) override;
      86                 :            :     /**
      87                 :            :      * Object editing is complete and the object should be saved.
      88                 :            :      *
      89                 :            :      * @param inst Object being edited
      90                 :            :      */
      91                 :            :     void commit(QofInstance*) override;
      92                 :            :     /**
      93                 :            :      * Object editing has been cancelled.
      94                 :            :      *
      95                 :            :      * @param inst Object being edited
      96                 :            :      */
      97                 :            :     void rollback(QofInstance*) override;
      98                 :            :     /** Connect the backend to a GncSqlConnection.
      99                 :            :      * Sets up version info. Calling with nullptr clears the connection and
     100                 :            :      * destroys the version info.
     101                 :            :      */
     102                 :            :     void connect(GncSqlConnection *conn) noexcept;
     103                 :            :     /**
     104                 :            :      * Initializes DB table version information.
     105                 :            :      */
     106                 :            :     void init_version_info() noexcept;
     107                 :            :     bool reset_version_info() noexcept;
     108                 :            :     /**
     109                 :            :      * Finalizes DB table version information.
     110                 :            :      */
     111                 :            :     void finalize_version_info() noexcept;
     112                 :            :     /* FIXME: These are just pass-throughs of m_conn functions. */
     113                 :            :     GncSqlStatementPtr create_statement_from_sql(const std::string& str) const noexcept;
     114                 :            :     /** Executes an SQL SELECT statement and returns the result rows.  If an
     115                 :            :      * error occurs, an entry is added to the log, an error status is returned
     116                 :            :      * to qof and nullptr is returned.
     117                 :            :      *
     118                 :            :      * @param statement Statement
     119                 :            :      * @return Results, or nullptr if an error has occurred
     120                 :            :      */
     121                 :            :     GncSqlResultPtr execute_select_statement(const GncSqlStatementPtr& stmt) const noexcept;
     122                 :            :     int execute_nonselect_statement(const GncSqlStatementPtr& stmt) const noexcept;
     123                 :            :     std::string quote_string(const std::string&) const noexcept;
     124                 :            :     /**
     125                 :            :      * Creates a table in the database
     126                 :            :      *
     127                 :            :      * @param table_name Table name
     128                 :            :      * @param col_table DB table description
     129                 :            :      * @return TRUE if successful, FALSE if unsuccessful
     130                 :            :      */
     131                 :            :     bool create_table(const std::string& table_name, const EntryVec& col_table) const noexcept;
     132                 :            :     /**
     133                 :            :      * Creates a table in the database and sets its version
     134                 :            :      *
     135                 :            :      * @param table_name Table name
     136                 :            :      * @param table_version Table version
     137                 :            :      * @param col_table DB table description
     138                 :            :      * @return TRUE if successful, FALSE if unsuccessful
     139                 :            :      */
     140                 :            :     bool create_table(const std::string& table_name, int table_version,
     141                 :            :                       const EntryVec& col_table) noexcept;
     142                 :            :     /**
     143                 :            :      * Create/update all tables in the database
     144                 :            :      */
     145                 :            :     void create_tables() noexcept;
     146                 :            : 
     147                 :            :     /**
     148                 :            :      * Creates an index in the database
     149                 :            :      *
     150                 :            :      * @param index_name Index name
     151                 :            :      * @param table_name Table name
     152                 :            :      * @param col_table Columns that the index should index
     153                 :            :      * @return TRUE if successful, FALSE if unsuccessful
     154                 :            :      */
     155                 :            :     bool create_index(const std::string& index_name,
     156                 :            :                       const std::string& table_name,
     157                 :            :                       const EntryVec& col_table) const noexcept;
     158                 :            :     /**
     159                 :            :      * Adds one or more columns to an existing table.
     160                 :            :      *
     161                 :            :      * @param table_name SQL table name
     162                 :            :      * @param new_col_table Column table for new columns
     163                 :            :      * @return TRUE if successful, FALSE if unsuccessful
     164                 :            :      */
     165                 :            :     bool add_columns_to_table(const std::string& table_name,
     166                 :            :                               const EntryVec& col_table) const noexcept;
     167                 :            :     /**
     168                 :            :      * Upgrades a table to a new structure.
     169                 :            :      *
     170                 :            :      * The upgrade is done by creating a new table with the new structure,
     171                 :            :      * SELECTing the old data into the new table, deleting the old table, then
     172                 :            :      * renaming the new table.  Therefore, this will only work if the new table
     173                 :            :      * structure is similar enough to the old table that the SELECT will work.
     174                 :            :      *
     175                 :            :      * @param table_name SQL table name
     176                 :            :      * @param col_table Column table
     177                 :            :      */
     178                 :            :     void upgrade_table (const std::string& table_name,
     179                 :            :                         const EntryVec& col_table) noexcept;
     180                 :            :     /**
     181                 :            :      * Returns the version number for a DB table.
     182                 :            :      *
     183                 :            :      * @param table_name Table name
     184                 :            :      * @return Version number, or 0 if the table does not exist
     185                 :            :      */
     186                 :            :     uint_t get_table_version(const std::string& table_name) const noexcept;
     187                 :            :     bool set_table_version (const std::string& table_name, uint_t version) noexcept;
     188                 :            :     /**
     189                 :            :      * Register a commodity to be committed after loading is complete.
     190                 :            :      *
     191                 :            :      * Necessary to save corrections made while loading.
     192                 :            :      * @param comm The commodity item to be committed.
     193                 :            :      */
     194                 :            :     void commodity_for_postload_processing(gnc_commodity*);
     195                 :            :     /**
     196                 :            :      * Get the GncSqlObjectBackend for the indicated type.
     197                 :            :      *
     198                 :            :      * Required because we need to pass a pointer to this to a callback via a C
     199                 :            :      * function.
     200                 :            :      * @param type: The QofInstance type constant to select the object backend.
     201                 :            :      */
     202                 :            :     GncSqlObjectBackendPtr get_object_backend(const std::string& type) const noexcept;
     203                 :            :     /**
     204                 :            :      * Checks whether an object is in the database or not.
     205                 :            :      *
     206                 :            :      * @param table_name DB table name
     207                 :            :      * @param obj_name QOF object type name
     208                 :            :      * @param pObject Object to be checked
     209                 :            :      * @param table DB table description
     210                 :            :      * @return TRUE if the object is in the database, FALSE otherwise
     211                 :            :      */
     212                 :            :     bool object_in_db (const char* table_name, QofIdTypeConst obj_name,
     213                 :            :                        const gpointer pObject, const EntryVec& table ) const noexcept;
     214                 :            :     /**
     215                 :            :      * Performs an operation on the database.
     216                 :            :      *
     217                 :            :      * @param op Operation type
     218                 :            :      * @param table_name SQL table name
     219                 :            :      * @param obj_name QOF object type name
     220                 :            :      * @param pObject Gnucash object
     221                 :            :      * @param table DB table description
     222                 :            :      * @return TRUE if successful, FALSE if not
     223                 :            :      */
     224                 :            :     bool do_db_operation (E_DB_OPERATION op, const char* table_name,
     225                 :            :                           QofIdTypeConst obj_name, gpointer pObject,
     226                 :            :                           const EntryVec& table) const noexcept;
     227                 :            :     /**
     228                 :            :      * Ensure that a commodity referenced in another object is in fact saved
     229                 :            :      * in the database.
     230                 :            :      *
     231                 :            :      * @param comm The commodity in question
     232                 :            :      * @return true if the commodity needed to be saved.
     233                 :            :      */
     234                 :            :     bool save_commodity(gnc_commodity* comm) noexcept;
     235                 :        409 :     QofBook* book() const noexcept { return m_book; }
     236                 :          0 :     void set_loading(bool loading) noexcept { m_loading = loading; }
     237                 :        188 :     bool pristine() const noexcept { return m_is_pristine_db; }
     238                 :            :     void update_progress(double pct) const noexcept;
     239                 :            :     void finish_progress() const noexcept;
     240                 :            : 
     241                 :            : protected:
     242                 :            :     GncSqlConnection* m_conn = nullptr;  /**< SQL connection */
     243                 :            :     QofBook* m_book = nullptr;           /**< The primary, main open book */
     244                 :            :     bool m_loading;        /**< We are performing an initial load */
     245                 :            :     bool m_in_query;       /**< We are processing a query */
     246                 :            :     bool m_is_pristine_db; /**< Are we saving to a new pristine db? */
     247                 :            :     const char* m_time_format = nullptr; /**< Server-specific date-time string format */
     248                 :            :     VersionVec m_versions;    /**< Version number for each table */
     249                 :            : private:
     250                 :            :     bool write_account_tree(Account*);
     251                 :            :     bool write_accounts();
     252                 :            :     bool write_transactions();
     253                 :            :     bool write_template_transactions();
     254                 :            :     bool write_schedXactions();
     255                 :            :     GncSqlStatementPtr build_insert_statement (const char* table_name,
     256                 :            :                                                QofIdTypeConst obj_name,
     257                 :            :                                                gpointer pObject,
     258                 :            :                                                const EntryVec& table) const noexcept;
     259                 :            :     GncSqlStatementPtr build_update_statement (const gchar* table_name,
     260                 :            :                                                QofIdTypeConst obj_name,
     261                 :            :                                                gpointer pObject,
     262                 :            :                                                const EntryVec& table) const noexcept;
     263                 :            :     GncSqlStatementPtr build_delete_statement (const char* table_name,
     264                 :            :                                                QofIdTypeConst obj_name,
     265                 :            :                                                gpointer pObject,
     266                 :            :                                                const EntryVec& table) const noexcept;
     267                 :            : 
     268                 :            :     class ObjectBackendRegistry
     269                 :            :     {
     270                 :            :     public:
     271                 :            :         ObjectBackendRegistry();
     272                 :            :         ObjectBackendRegistry(const ObjectBackendRegistry&) = delete;
     273                 :            :         ObjectBackendRegistry(const ObjectBackendRegistry&&) = delete;
     274                 :            :         ObjectBackendRegistry operator=(const ObjectBackendRegistry&) = delete;
     275                 :            :         ObjectBackendRegistry operator=(const ObjectBackendRegistry&&) = delete;
     276                 :         10 :         ~ObjectBackendRegistry() = default;
     277                 :            :         void register_backend(OBEEntry&& entry) noexcept;
     278                 :            :         void register_backend(GncSqlObjectBackendPtr obe) noexcept;
     279                 :            :         GncSqlObjectBackendPtr get_object_backend(const std::string& type) const;
     280                 :            :         void load_remaining(GncSqlBackend*);
     281                 :         15 :         OBEVec::iterator begin() { return m_registry.begin(); }
     282                 :         15 :         OBEVec::iterator end() { return m_registry.end(); }
     283                 :          5 :         OBEVec::size_type size() { return m_registry.size(); }
     284                 :            :     private:
     285                 :            :         OBEVec m_registry;
     286                 :            :     };
     287                 :            :     ObjectBackendRegistry m_backend_registry;
     288                 :            :     std::vector<gnc_commodity*> m_postload_commodities;
     289                 :            : };
     290                 :            : 
     291                 :            : #endif //__GNC_SQL_BACKEND_HPP__

Generated by: LCOV version 1.14