mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-12-01 21:19:16 -06:00
1cec0cb3f3
- removes warnings compiling swig engine ... [ 10%] Generating swig-engine.cpp .../libgnucash/engine/engine-helpers.h:31: Warning 313: Unrecognized extern type "C++". .../libgnucash/engine/gnc-date.h:83: Warning 313: Unrecognized extern type "C++". .../libgnucash/engine/qofquery.h:90: Warning 302: Identifier 'QofQuery' redefined (ignored), .../libgnucash/engine/gnc-option.hpp:55: Warning 302: previous definition of 'QofQuery'. .../libgnucash/engine/gnc-commodity.h:56: Warning 313: Unrecognized extern type "C++". .../libgnucash/engine/gncBusiness.h:40: Warning 313: Unrecognized extern type "C++". .../libgnucash/engine/gncEntry.h:37: Warning 313: Unrecognized extern type "C++".
292 lines
12 KiB
C++
292 lines
12 KiB
C++
/***********************************************************************\
|
|
* gnc-sql-backend.hpp: Qof Backend for SQL Databases *
|
|
* *
|
|
* Copyright 2016 John Ralls <jralls@ceridwen.us> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU General Public License as *
|
|
* published by the Free Software Foundation; either version 2 of *
|
|
* the License, or (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, contact: *
|
|
* *
|
|
* Free Software Foundation Voice: +1-617-542-5942 *
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
|
\***********************************************************************/
|
|
|
|
#ifndef __GNC_SQL_BACKEND_HPP__
|
|
#define __GNC_SQL_BACKEND_HPP__
|
|
|
|
#include <qof.h>
|
|
#include <Account.h>
|
|
|
|
#include <memory>
|
|
#include <exception>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <qof-backend.hpp>
|
|
|
|
class GncSqlColumnTableEntry;
|
|
using GncSqlColumnTableEntryPtr = std::shared_ptr<GncSqlColumnTableEntry>;
|
|
using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
|
|
class GncSqlObjectBackend;
|
|
using GncSqlObjectBackendPtr = std::shared_ptr<GncSqlObjectBackend>;
|
|
using OBEEntry = std::tuple<std::string, GncSqlObjectBackendPtr>;
|
|
using OBEVec = std::vector<OBEEntry>;
|
|
class GncSqlConnection;
|
|
class GncSqlStatement;
|
|
using GncSqlStatementPtr = std::unique_ptr<GncSqlStatement>;
|
|
class GncSqlResult;
|
|
using GncSqlResultPtr = GncSqlResult*;
|
|
using VersionPair = std::pair<const std::string, unsigned int>;
|
|
using VersionVec = std::vector<VersionPair>;
|
|
using uint_t = unsigned int;
|
|
|
|
typedef enum
|
|
{
|
|
OP_DB_INSERT,
|
|
OP_DB_UPDATE,
|
|
OP_DB_DELETE
|
|
} E_DB_OPERATION;
|
|
|
|
/**
|
|
*
|
|
* Main SQL backend structure.
|
|
*/
|
|
class GncSqlBackend : public QofBackend
|
|
{
|
|
public:
|
|
GncSqlBackend(GncSqlConnection *conn, QofBook* book);
|
|
virtual ~GncSqlBackend();
|
|
/**
|
|
* Load the contents of an SQL database into a book.
|
|
*
|
|
* @param book Book to be loaded
|
|
*/
|
|
void load(QofBook*, QofBackendLoadType) override;
|
|
/**
|
|
* Save the contents of a book to an SQL database.
|
|
*
|
|
* @param book Book to be saved
|
|
*/
|
|
void sync(QofBook*) override;
|
|
/**
|
|
* An object is about to be edited.
|
|
*
|
|
* @param inst Object being edited
|
|
*/
|
|
void begin(QofInstance*) override;
|
|
/**
|
|
* Object editing is complete and the object should be saved.
|
|
*
|
|
* @param inst Object being edited
|
|
*/
|
|
void commit(QofInstance*) override;
|
|
/**
|
|
* Object editing has been cancelled.
|
|
*
|
|
* @param inst Object being edited
|
|
*/
|
|
void rollback(QofInstance*) override;
|
|
/** Connect the backend to a GncSqlConnection.
|
|
* Sets up version info. Calling with nullptr clears the connection and
|
|
* destroys the version info.
|
|
*/
|
|
void connect(GncSqlConnection *conn) noexcept;
|
|
/**
|
|
* Initializes DB table version information.
|
|
*/
|
|
void init_version_info() noexcept;
|
|
bool reset_version_info() noexcept;
|
|
/**
|
|
* Finalizes DB table version information.
|
|
*/
|
|
void finalize_version_info() noexcept;
|
|
/* FIXME: These are just pass-throughs of m_conn functions. */
|
|
GncSqlStatementPtr create_statement_from_sql(const std::string& str) const noexcept;
|
|
/** Executes an SQL SELECT statement and returns the result rows. If an
|
|
* error occurs, an entry is added to the log, an error status is returned
|
|
* to qof and nullptr is returned.
|
|
*
|
|
* @param statement Statement
|
|
* @return Results, or nullptr if an error has occurred
|
|
*/
|
|
GncSqlResultPtr execute_select_statement(const GncSqlStatementPtr& stmt) const noexcept;
|
|
int execute_nonselect_statement(const GncSqlStatementPtr& stmt) const noexcept;
|
|
std::string quote_string(const std::string&) const noexcept;
|
|
/**
|
|
* Creates a table in the database
|
|
*
|
|
* @param table_name Table name
|
|
* @param col_table DB table description
|
|
* @return TRUE if successful, FALSE if unsuccessful
|
|
*/
|
|
bool create_table(const std::string& table_name, const EntryVec& col_table) const noexcept;
|
|
/**
|
|
* Creates a table in the database and sets its version
|
|
*
|
|
* @param table_name Table name
|
|
* @param table_version Table version
|
|
* @param col_table DB table description
|
|
* @return TRUE if successful, FALSE if unsuccessful
|
|
*/
|
|
bool create_table(const std::string& table_name, int table_version,
|
|
const EntryVec& col_table) noexcept;
|
|
/**
|
|
* Create/update all tables in the database
|
|
*/
|
|
void create_tables() noexcept;
|
|
|
|
/**
|
|
* Creates an index in the database
|
|
*
|
|
* @param index_name Index name
|
|
* @param table_name Table name
|
|
* @param col_table Columns that the index should index
|
|
* @return TRUE if successful, FALSE if unsuccessful
|
|
*/
|
|
bool create_index(const std::string& index_name,
|
|
const std::string& table_name,
|
|
const EntryVec& col_table) const noexcept;
|
|
/**
|
|
* Adds one or more columns to an existing table.
|
|
*
|
|
* @param table_name SQL table name
|
|
* @param new_col_table Column table for new columns
|
|
* @return TRUE if successful, FALSE if unsuccessful
|
|
*/
|
|
bool add_columns_to_table(const std::string& table_name,
|
|
const EntryVec& col_table) const noexcept;
|
|
/**
|
|
* Upgrades a table to a new structure.
|
|
*
|
|
* The upgrade is done by creating a new table with the new structure,
|
|
* SELECTing the old data into the new table, deleting the old table, then
|
|
* renaming the new table. Therefore, this will only work if the new table
|
|
* structure is similar enough to the old table that the SELECT will work.
|
|
*
|
|
* @param table_name SQL table name
|
|
* @param col_table Column table
|
|
*/
|
|
void upgrade_table (const std::string& table_name,
|
|
const EntryVec& col_table) noexcept;
|
|
/**
|
|
* Returns the version number for a DB table.
|
|
*
|
|
* @param table_name Table name
|
|
* @return Version number, or 0 if the table does not exist
|
|
*/
|
|
uint_t get_table_version(const std::string& table_name) const noexcept;
|
|
bool set_table_version (const std::string& table_name, uint_t version) noexcept;
|
|
/**
|
|
* Register a commodity to be committed after loading is complete.
|
|
*
|
|
* Necessary to save corrections made while loading.
|
|
* @param comm The commodity item to be committed.
|
|
*/
|
|
void commodity_for_postload_processing(gnc_commodity*);
|
|
/**
|
|
* Get the GncSqlObjectBackend for the indicated type.
|
|
*
|
|
* Required because we need to pass a pointer to this to a callback via a C
|
|
* function.
|
|
* @param type: The QofInstance type constant to select the object backend.
|
|
*/
|
|
GncSqlObjectBackendPtr get_object_backend(const std::string& type) const noexcept;
|
|
/**
|
|
* Checks whether an object is in the database or not.
|
|
*
|
|
* @param table_name DB table name
|
|
* @param obj_name QOF object type name
|
|
* @param pObject Object to be checked
|
|
* @param table DB table description
|
|
* @return TRUE if the object is in the database, FALSE otherwise
|
|
*/
|
|
bool object_in_db (const char* table_name, QofIdTypeConst obj_name,
|
|
const gpointer pObject, const EntryVec& table ) const noexcept;
|
|
/**
|
|
* Performs an operation on the database.
|
|
*
|
|
* @param op Operation type
|
|
* @param table_name SQL table name
|
|
* @param obj_name QOF object type name
|
|
* @param pObject Gnucash object
|
|
* @param table DB table description
|
|
* @return TRUE if successful, FALSE if not
|
|
*/
|
|
bool do_db_operation (E_DB_OPERATION op, const char* table_name,
|
|
QofIdTypeConst obj_name, gpointer pObject,
|
|
const EntryVec& table) const noexcept;
|
|
/**
|
|
* Ensure that a commodity referenced in another object is in fact saved
|
|
* in the database.
|
|
*
|
|
* @param comm The commodity in question
|
|
* @return true if the commodity needed to be saved.
|
|
*/
|
|
bool save_commodity(gnc_commodity* comm) noexcept;
|
|
QofBook* book() const noexcept { return m_book; }
|
|
void set_loading(bool loading) noexcept { m_loading = loading; }
|
|
bool pristine() const noexcept { return m_is_pristine_db; }
|
|
void update_progress(double pct) const noexcept;
|
|
void finish_progress() const noexcept;
|
|
|
|
protected:
|
|
GncSqlConnection* m_conn = nullptr; /**< SQL connection */
|
|
QofBook* m_book = nullptr; /**< The primary, main open book */
|
|
bool m_loading; /**< We are performing an initial load */
|
|
bool m_in_query; /**< We are processing a query */
|
|
bool m_is_pristine_db; /**< Are we saving to a new pristine db? */
|
|
const char* m_time_format = nullptr; /**< Server-specific date-time string format */
|
|
VersionVec m_versions; /**< Version number for each table */
|
|
private:
|
|
bool write_account_tree(Account*);
|
|
bool write_accounts();
|
|
bool write_transactions();
|
|
bool write_template_transactions();
|
|
bool write_schedXactions();
|
|
GncSqlStatementPtr build_insert_statement (const char* table_name,
|
|
QofIdTypeConst obj_name,
|
|
gpointer pObject,
|
|
const EntryVec& table) const noexcept;
|
|
GncSqlStatementPtr build_update_statement (const gchar* table_name,
|
|
QofIdTypeConst obj_name,
|
|
gpointer pObject,
|
|
const EntryVec& table) const noexcept;
|
|
GncSqlStatementPtr build_delete_statement (const char* table_name,
|
|
QofIdTypeConst obj_name,
|
|
gpointer pObject,
|
|
const EntryVec& table) const noexcept;
|
|
|
|
class ObjectBackendRegistry
|
|
{
|
|
public:
|
|
ObjectBackendRegistry();
|
|
ObjectBackendRegistry(const ObjectBackendRegistry&) = delete;
|
|
ObjectBackendRegistry(const ObjectBackendRegistry&&) = delete;
|
|
ObjectBackendRegistry operator=(const ObjectBackendRegistry&) = delete;
|
|
ObjectBackendRegistry operator=(const ObjectBackendRegistry&&) = delete;
|
|
~ObjectBackendRegistry() = default;
|
|
void register_backend(OBEEntry&& entry) noexcept;
|
|
void register_backend(GncSqlObjectBackendPtr obe) noexcept;
|
|
GncSqlObjectBackendPtr get_object_backend(const std::string& type) const;
|
|
void load_remaining(GncSqlBackend*);
|
|
OBEVec::iterator begin() { return m_registry.begin(); }
|
|
OBEVec::iterator end() { return m_registry.end(); }
|
|
OBEVec::size_type size() { return m_registry.size(); }
|
|
private:
|
|
OBEVec m_registry;
|
|
};
|
|
ObjectBackendRegistry m_backend_registry;
|
|
std::vector<gnc_commodity*> m_postload_commodities;
|
|
};
|
|
|
|
#endif //__GNC_SQL_BACKEND_HPP__
|