Replace C API with C++ API for functions used by GncSqlDbiBackend.

Since these are now parent-class member functions they can be called
directly from dbi_be without any casting gymnastics.

Also: Move the GncSqlObjectBackend registry to its own class, a private
member of GncSqlBackend. This eliminates a static variable in gnc-backend-sql.cpp
and allows the GncSqlBackend::ObjectRegistry constructor to insert all of
the backends into the list, eliminating gnc_sql_init() and all of the
gnc_sql_init_foo_handler() functions. The cost of this is that the objects
are now created on the free store instead of the text segment.

Because the object backends are created at GncSqlBackend construction
there is now a GncSqlBookBackend in the registry and the second error
message in test_gnc_sql_commit_edit is no longer emitted; instead, the
object is properly committed.
This commit is contained in:
John Ralls 2016-11-03 14:21:11 -07:00
parent b2a644c29d
commit ee0e61a07e
47 changed files with 891 additions and 1099 deletions

View File

@ -230,17 +230,6 @@ UriStrings::quote_dbname(DbType t) const noexcept
return retval;
}
static void
create_tables(const OBEEntry& entry, GncDbiBackend* dbi_be)
{
std::string type;
GncSqlObjectBackendPtr obe = nullptr;
std::tie(type, obe) = entry;
g_return_if_fail(obe->is_version (GNC_SQL_BACKEND_VERSION));
obe->create_tables (dbi_be);
}
static void
set_options(dbi_conn conn, const PairVec& options)
{
@ -872,14 +861,10 @@ gnc_dbi_load (QofBackend* qof_be, QofBook* book, QofBackendLoadType loadType)
// Set up table version information
dbi_be->init_version_info ();
assert (dbi_be->m_book == nullptr);
// Call all object backends to create any required tables
auto registry = gnc_sql_get_backend_registry();
for (auto entry : registry)
create_tables(entry, dbi_be);
dbi_be->create_tables();
}
gnc_sql_load (dbi_be, book, loadType);
dbi_be->load(book, loadType);
if (GNUCASH_RESAVE_VERSION > dbi_be->get_table_version("Gnucash"))
{
@ -961,7 +946,7 @@ gnc_dbi_safe_sync_all (QofBackend* qof_be, QofBook* book)
}
}
gnc_sql_sync_all (dbi_be, book);
dbi_be->sync_all(book);
if (qof_backend_check_error (qof_be))
{
conn->table_operation (table_list, rollback);
@ -980,7 +965,7 @@ gnc_dbi_begin_edit (QofBackend* qof_be, QofInstance* inst)
g_return_if_fail (dbi_be != nullptr);
g_return_if_fail (inst != nullptr);
gnc_sql_begin_edit (dbi_be, inst);
dbi_be->begin_edit(inst);
}
static void
@ -991,7 +976,7 @@ gnc_dbi_rollback_edit (QofBackend* qof_be, QofInstance* inst)
g_return_if_fail (dbi_be != nullptr);
g_return_if_fail (inst != nullptr);
gnc_sql_rollback_edit (dbi_be, inst);
dbi_be->rollback_edit(inst);
}
static void
@ -1002,7 +987,7 @@ gnc_dbi_commit_edit (QofBackend* qof_be, QofInstance* inst)
g_return_if_fail (dbi_be != nullptr);
g_return_if_fail (inst != nullptr);
gnc_sql_commit_edit (dbi_be, inst);
dbi_be->commit_edit(inst);
}
/* ================================================================= */
@ -1028,13 +1013,11 @@ init_sql_backend (GncDbiBackend* dbi_be)
qof_be->safe_sync = gnc_dbi_safe_sync_all;
/* CoA Export function not implemented for the SQL backend. */
qof_be->export_fn = nullptr;
gnc_sql_init (dbi_be);
}
/*
* Checks to see whether the file is an sqlite file or not
*1980
*
*/
template<> bool
QofDbiBackendProvider<DbType::DBI_SQLITE>::type_check(const char *uri)

View File

@ -94,17 +94,9 @@ static EntryVec parent_col_table
"parent_guid", 0, 0, nullptr, (QofSetterFunc)set_parent_guid),
});
class GncSqlAccountBackend : public GncSqlObjectBackend
{
public:
GncSqlAccountBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override;
};
GncSqlAccountBackend::GncSqlAccountBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_ACCOUNT,
TABLE_NAME, col_table) {}
typedef struct
{
@ -417,12 +409,5 @@ GncSqlColumnTableEntryImpl<CT_ACCOUNTREF>::add_to_query(const GncSqlBackend* sql
{
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_sql_init_account_handler (void)
{
static GncSqlAccountBackend be_data{
GNC_SQL_BACKEND_VERSION, GNC_ID_ACCOUNT, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -29,12 +29,14 @@
#ifndef GNC_ACCOUNT_SQL_H
#define GNC_ACCOUNT_SQL_H
#include "gnc-backend-sql.h"
extern "C"
#include "gnc-sql-object-backend.hpp"
class GncSqlAccountBackend : public GncSqlObjectBackend
{
#include "qof.h"
}
void gnc_sql_init_account_handler (void);
gboolean gnc_sql_save_account (GncSqlBackend* sql_be, QofInstance* inst);
public:
GncSqlAccountBackend();
void load_all(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override;
};
#endif /* GNC_ACCOUNT_SQL_H */

View File

@ -103,531 +103,12 @@ static GncSqlStatementPtr build_delete_statement (GncSqlBackend* sql_be,
gpointer pObject,
const EntryVec& table);
static GList* post_load_commodities = NULL;
#define TRANSACTION_NAME "trans"
typedef struct
{
QofIdType searchObj;
gpointer pCompiledQuery;
} gnc_sql_query_info;
/* callback structure */
typedef struct
{
gboolean is_known;
gboolean is_ok;
GncSqlBackend* sql_be;
QofInstance* inst;
QofQuery* pQuery;
gpointer pCompiledQuery;
gnc_sql_query_info* pQueryInfo;
} sql_backend;
static QofLogModule log_module = G_LOG_DOMAIN;
#define SQLITE_PROVIDER_NAME "SQLite"
/* ================================================================= */
static OBEVec backend_registry;
void
gnc_sql_register_backend(OBEEntry&& entry)
{
backend_registry.emplace_back(entry);
}
void
gnc_sql_register_backend(GncSqlObjectBackendPtr obe)
{
backend_registry.emplace_back(make_tuple(std::string{obe->type()}, obe));
}
const OBEVec&
gnc_sql_get_backend_registry()
{
return backend_registry;
}
GncSqlObjectBackendPtr
gnc_sql_get_object_backend(const std::string& type)
{
auto entry = std::find_if(backend_registry.begin(),
backend_registry.end(),
[type](const OBEEntry& entry){
return type == std::get<0>(entry);
});
if (entry == backend_registry.end())
return nullptr;
return std::get<1>(*entry);
}
void
gnc_sql_init(GncSqlBackend* sql_be)
{
static gboolean initialized = FALSE;
if (!initialized)
{
gnc_sql_init_object_handlers ();
initialized = TRUE;
}
}
/* ================================================================= */
static void
create_tables(const OBEEntry& entry, GncSqlBackend* sql_be)
{
std::string type;
GncSqlObjectBackendPtr obe = nullptr;
std::tie(type, obe) = entry;
g_return_if_fail (obe->is_version (GNC_SQL_BACKEND_VERSION));
sql_be->update_progress();
obe->create_tables(sql_be);
}
/* ================================================================= */
/* Main object load order */
static const StrVec fixed_load_order
{ GNC_ID_BOOK, GNC_ID_COMMODITY, GNC_ID_ACCOUNT, GNC_ID_LOT };
/* Order in which business objects need to be loaded */
static const StrVec business_fixed_load_order =
{ GNC_ID_BILLTERM, GNC_ID_TAXTABLE, GNC_ID_INVOICE };
static void
initial_load(const OBEEntry& entry, GncSqlBackend* sql_be)
{
std::string type;
GncSqlObjectBackendPtr obe = nullptr;
std::tie(type, obe) = entry;
g_return_if_fail(obe->is_version (GNC_SQL_BACKEND_VERSION));
/* Don't need to load anything if it has already been loaded with
* the fixed order.
*/
if (std::find(fixed_load_order.begin(), fixed_load_order.end(),
type) != fixed_load_order.end()) return;
if (std::find(business_fixed_load_order.begin(), business_fixed_load_order.end(),
type) != business_fixed_load_order.end()) return;
obe->load_all (sql_be);
}
void
gnc_sql_push_commodity_for_postload_processing (GncSqlBackend* sql_be,
gpointer comm)
{
post_load_commodities = g_list_prepend (post_load_commodities, comm);
}
static void
commit_commodity (gpointer data)
{
gnc_commodity* comm = GNC_COMMODITY (data);
gnc_sql_commit_commodity (comm);
}
void
gnc_sql_load (GncSqlBackend* sql_be, QofBook* book, QofBackendLoadType loadType)
{
Account* root;
g_return_if_fail (sql_be != NULL);
g_return_if_fail (book != NULL);
ENTER ("sql_be=%p, book=%p", sql_be, book);
sql_be->m_loading = TRUE;
if (loadType == LOAD_TYPE_INITIAL_LOAD)
{
g_assert (sql_be->m_book == NULL);
sql_be->m_book = book;
/* Load any initial stuff. Some of this needs to happen in a certain order */
for (auto type : fixed_load_order)
{
auto obe = gnc_sql_get_object_backend(type);
if (obe)
{
sql_be->update_progress();
obe->load_all (sql_be);
}
}
for (auto type : business_fixed_load_order)
{
auto obe = gnc_sql_get_object_backend(type);
if (obe)
{
sql_be->update_progress();
obe->load_all (sql_be);
}
}
root = gnc_book_get_root_account( book );
gnc_account_foreach_descendant(root, (AccountCb)xaccAccountBeginEdit,
nullptr);
for (auto entry : backend_registry)
initial_load(entry, sql_be);
gnc_account_foreach_descendant(root, (AccountCb)xaccAccountCommitEdit,
nullptr);
}
else if (loadType == LOAD_TYPE_LOAD_ALL)
{
// Load all transactions
auto obe = gnc_sql_get_object_backend (GNC_ID_TRANS);
obe->load_all (sql_be);
}
sql_be->m_loading = FALSE;
g_list_free_full (post_load_commodities, commit_commodity);
post_load_commodities = NULL;
/* Mark the sessoion as clean -- though it should never be marked
* dirty with this backend
*/
qof_book_mark_session_saved (book);
sql_be->finish_progress();
LEAVE ("");
}
/* ================================================================= */
static gboolean
write_account_tree (GncSqlBackend* sql_be, Account* root)
{
GList* descendants;
GList* node;
gboolean is_ok = TRUE;
g_return_val_if_fail (sql_be != NULL, FALSE);
g_return_val_if_fail (root != NULL, FALSE);
auto obe = gnc_sql_get_object_backend (GNC_ID_ACCOUNT);
is_ok = obe->commit (sql_be, QOF_INSTANCE (root));
if (is_ok)
{
descendants = gnc_account_get_descendants (root);
for (node = descendants; node != NULL && is_ok; node = g_list_next (node))
{
is_ok = obe->commit(sql_be, QOF_INSTANCE (GNC_ACCOUNT (node->data)));
if (!is_ok) break;
}
g_list_free (descendants);
}
sql_be->update_progress();
return is_ok;
}
static gboolean
write_accounts (GncSqlBackend* sql_be)
{
gboolean is_ok;
g_return_val_if_fail (sql_be != NULL, FALSE);
sql_be->update_progress();
is_ok = write_account_tree (sql_be, gnc_book_get_root_account (sql_be->book()));
if (is_ok)
{
sql_be->update_progress();
is_ok = write_account_tree (sql_be, gnc_book_get_template_root (sql_be->book()));
}
return is_ok;
}
static gboolean
write_tx (Transaction* tx, gpointer data)
{
auto s = static_cast<write_objects_t*>(data);
g_return_val_if_fail (tx != NULL, 0);
g_return_val_if_fail (data != NULL, 0);
s->commit (QOF_INSTANCE (tx));
auto splitbe = gnc_sql_get_object_backend (GNC_ID_SPLIT);
for (auto split_node = xaccTransGetSplitList (tx);
split_node != nullptr && s->is_ok;
split_node = g_list_next (split_node))
{
s->is_ok = splitbe->commit(s->be, QOF_INSTANCE(split_node->data));
}
s->be->update_progress ();
return (s->is_ok ? 0 : 1);
}
static gboolean
write_transactions (GncSqlBackend* sql_be)
{
g_return_val_if_fail (sql_be != NULL, FALSE);
auto obe = gnc_sql_get_object_backend(GNC_ID_TRANS);
write_objects_t data{sql_be, true, obe};
(void)xaccAccountTreeForEachTransaction (
gnc_book_get_root_account (sql_be->book()), write_tx, &data);
sql_be->update_progress();
return data.is_ok;
}
static gboolean
write_template_transactions (GncSqlBackend* sql_be)
{
g_return_val_if_fail (sql_be != NULL, FALSE);
auto obe = gnc_sql_get_object_backend(GNC_ID_TRANS);
write_objects_t data{sql_be, true, obe};
auto ra = gnc_book_get_template_root (sql_be->book());
if (gnc_account_n_descendants (ra) > 0)
{
(void)xaccAccountTreeForEachTransaction (ra, write_tx, &data);
sql_be->update_progress();
}
return data.is_ok;
}
static gboolean
write_schedXactions (GncSqlBackend* sql_be)
{
GList* schedXactions;
SchedXaction* tmpSX;
gboolean is_ok = TRUE;
g_return_val_if_fail (sql_be != NULL, FALSE);
schedXactions = gnc_book_get_schedxactions (sql_be->book())->sx_list;
auto obe = gnc_sql_get_object_backend(GNC_ID_SCHEDXACTION);
for (; schedXactions != NULL && is_ok; schedXactions = schedXactions->next)
{
tmpSX = static_cast<decltype (tmpSX)> (schedXactions->data);
is_ok = obe->commit (sql_be, QOF_INSTANCE (tmpSX));
}
sql_be->update_progress();
return is_ok;
}
#pragma GCC diagnostic warning "-Wformat-nonliteral"
void
gnc_sql_sync_all (GncSqlBackend* sql_be, QofBook* book)
{
gboolean is_ok;
g_return_if_fail (sql_be != NULL);
g_return_if_fail (book != NULL);
sql_be->reset_version_info();
ENTER ("book=%p, sql_be->book=%p", book, sql_be->book());
sql_be->update_progress();
/* Create new tables */
sql_be->m_is_pristine_db = true;
for(auto entry : backend_registry)
create_tables(entry, sql_be);
/* Save all contents */
sql_be->m_book = book;
is_ok = sql_be->m_conn->begin_transaction ();
// FIXME: should write the set of commodities that are used
//write_commodities( sql_be, book );
if (is_ok)
{
auto obe = gnc_sql_get_object_backend(GNC_ID_BOOK);
is_ok = obe->commit (sql_be, QOF_INSTANCE (book));
}
if (is_ok)
{
is_ok = write_accounts (sql_be);
}
if (is_ok)
{
is_ok = write_transactions (sql_be);
}
if (is_ok)
{
is_ok = write_template_transactions (sql_be);
}
if (is_ok)
{
is_ok = write_schedXactions (sql_be);
}
if (is_ok)
{
for (auto entry : backend_registry)
std::get<1>(entry)->write (sql_be);
}
if (is_ok)
{
is_ok = sql_be->m_conn->commit_transaction ();
}
if (is_ok)
{
sql_be->m_is_pristine_db = false;
/* Mark the session as clean -- though it shouldn't ever get
* marked dirty with this backend
*/
qof_book_mark_session_saved (book);
}
else
{
if (!qof_backend_check_error ((QofBackend*)sql_be))
qof_backend_set_error ((QofBackend*)sql_be, ERR_BACKEND_SERVER_ERR);
is_ok = sql_be->m_conn->rollback_transaction ();
}
sql_be->finish_progress();
LEAVE ("book=%p", book);
}
/* ================================================================= */
/* Routines to deal with the creation of multiple books. */
void
gnc_sql_begin_edit (GncSqlBackend* sql_be, QofInstance* inst)
{
g_return_if_fail (sql_be != NULL);
g_return_if_fail (inst != NULL);
ENTER (" ");
LEAVE ("");
}
void
gnc_sql_rollback_edit (GncSqlBackend* sql_be, QofInstance* inst)
{
g_return_if_fail (sql_be != NULL);
g_return_if_fail (inst != NULL);
ENTER (" ");
LEAVE ("");
}
static void
commit(const OBEEntry& entry, sql_backend* be_data)
{
std::string type;
GncSqlObjectBackendPtr obe= nullptr;
std::tie(type, obe) = entry;
g_return_if_fail (obe->is_version (GNC_SQL_BACKEND_VERSION));
/* If this has already been handled, or is not the correct
* handler, return
*/
if (type != std::string{be_data->inst->e_type}) return;
if (be_data->is_known) return;
be_data->is_ok = obe->commit (be_data->sql_be, be_data->inst);
be_data->is_known = TRUE;
}
/* Commit_edit handler - find the correct backend handler for this object
* type and call its commit handler
*/
void
gnc_sql_commit_edit (GncSqlBackend* sql_be, QofInstance* inst)
{
sql_backend be_data;
gboolean is_dirty;
gboolean is_destroying;
gboolean is_infant;
g_return_if_fail (sql_be != NULL);
g_return_if_fail (inst != NULL);
if (qof_book_is_readonly (sql_be->book()))
{
qof_backend_set_error ((QofBackend*)sql_be, ERR_BACKEND_READONLY);
(void)sql_be->m_conn->rollback_transaction ();
return;
}
/* During initial load where objects are being created, don't commit
anything, but do mark the object as clean. */
if (sql_be->m_loading)
{
qof_instance_mark_clean (inst);
return;
}
// The engine has a PriceDB object but it isn't in the database
if (strcmp (inst->e_type, "PriceDB") == 0)
{
qof_instance_mark_clean (inst);
qof_book_mark_session_saved (sql_be->book());
return;
}
ENTER (" ");
is_dirty = qof_instance_get_dirty_flag (inst);
is_destroying = qof_instance_get_destroying (inst);
is_infant = qof_instance_get_infant (inst);
DEBUG ("%s dirty = %d, do_free = %d, infant = %d\n",
(inst->e_type ? inst->e_type : "(null)"),
is_dirty, is_destroying, is_infant);
if (!is_dirty && !is_destroying)
{
LEAVE ("!dirty OR !destroying");
return;
}
if (!sql_be->m_conn->begin_transaction ())
{
PERR ("gnc_sql_commit_edit(): begin_transaction failed\n");
LEAVE ("Rolled back - database transaction begin error");
return;
}
be_data.is_known = FALSE;
be_data.sql_be = sql_be;
be_data.inst = inst;
be_data.is_ok = TRUE;
for (auto entry : backend_registry)
commit(entry, &be_data);
if (!be_data.is_known)
{
PERR ("gnc_sql_commit_edit(): Unknown object type '%s'\n", inst->e_type);
(void)sql_be->m_conn->rollback_transaction ();
// Don't let unknown items still mark the book as being dirty
qof_book_mark_session_saved (sql_be->book());
qof_instance_mark_clean (inst);
LEAVE ("Rolled back - unknown object type");
return;
}
if (!be_data.is_ok)
{
// Error - roll it back
(void)sql_be->m_conn->rollback_transaction ();
// This *should* leave things marked dirty
LEAVE ("Rolled back - database error");
return;
}
(void)sql_be->m_conn->commit_transaction ();
qof_book_mark_session_saved (sql_be->book());
qof_instance_mark_clean (inst);
LEAVE ("");
}
/* ---------------------------------------------------------------------- */
/* Query processing */
@ -1276,43 +757,4 @@ build_delete_statement (GncSqlBackend* sql_be,
return stmt;
}
/* ================================================================= */
/* ================================================================= */
/* ================================================================= */
static void
business_core_sql_init (void)
{
/* Initialize our pointers into the backend subsystem */
gnc_billterm_sql_initialize ();
gnc_customer_sql_initialize ();
gnc_employee_sql_initialize ();
gnc_entry_sql_initialize ();
gnc_invoice_sql_initialize ();
gnc_job_sql_initialize ();
gnc_order_sql_initialize ();
gnc_taxtable_sql_initialize ();
gnc_vendor_sql_initialize ();
}
static void
gnc_sql_init_object_handlers (void)
{
gnc_sql_init_book_handler ();
gnc_sql_init_commodity_handler ();
gnc_sql_init_account_handler ();
gnc_sql_init_budget_handler ();
gnc_sql_init_price_handler ();
gnc_sql_init_transaction_handler ();
gnc_sql_init_slots_handler ();
gnc_sql_init_recurrence_handler ();
gnc_sql_init_schedxaction_handler ();
gnc_sql_init_lot_handler ();
/* And the business objects */
business_core_sql_init ();
}
/* ========================== END OF FILE ===================== */

View File

@ -51,101 +51,13 @@ extern "C"
#include "gnc-sql-object-backend.hpp"
using StrVec = std::vector<std::string>;
using InstanceVec = std::vector<QofInstance*>;
using PairVec = std::vector<std::pair<std::string, std::string>>;
using uint_t = unsigned int;
class GncSqlRow;
/**
* Initialize the SQL backend.
*
* @param sql_be SQL backend
*/
void gnc_sql_init (GncSqlBackend* sql_be);
/**
* Load the contents of an SQL database into a book.
*
* @param sql_be SQL backend
* @param book Book to be loaded
*/
void gnc_sql_load (GncSqlBackend* sql_be, QofBook* book,
QofBackendLoadType loadType);
/**
* Register a commodity to be committed after loading is complete.
*
* Necessary to save corrections made while loading.
* @param sql_be SQL backend
* @param comm The commodity item to be committed.
*/
void gnc_sql_push_commodity_for_postload_processing (GncSqlBackend* sql_be,
gpointer comm);
/**
* Save the contents of a book to an SQL database.
*
* @param sql_be SQL backend
* @param book Book to be saved
*/
void gnc_sql_sync_all (GncSqlBackend* sql_be, QofBook* book);
/**
* An object is about to be edited.
*
* @param sql_be SQL backend
* @param inst Object being edited
*/
void gnc_sql_begin_edit (GncSqlBackend* sql_be, QofInstance* inst);
/**
* Object editing has been cancelled.
*
* @param qsql_be SQL backend
* @param inst Object being edited
*/
void gnc_sql_rollback_edit (GncSqlBackend* qsql_be, QofInstance* inst);
/**
* Object editting is complete and the object should be saved.
*
* @param qsql_be SQL backend
* @param inst Object being edited
*/
void gnc_sql_commit_edit (GncSqlBackend* qsql_be, QofInstance* inst);
/**
*/
#define GNC_SQL_BACKEND "gnc:sql:1"
#define GNC_SQL_BACKEND_VERSION 1
void gnc_sql_register_backend(OBEEntry&&);
void gnc_sql_register_backend(GncSqlObjectBackendPtr);
const OBEVec& gnc_sql_get_backend_registry();
GncSqlObjectBackendPtr gnc_sql_get_object_backend(const std::string& table_name);
/**
* Data-passing struct for callbacks to qof_object_foreach() used in
* GncSqlObjectBackend::write(). Once QofCollection is rewritten to use C++
* containers we'll use std::foreach() and lambdas instead of callbacks and this
* can go away.
*/
struct write_objects_t
{
write_objects_t() = default;
write_objects_t (GncSqlBackend* sql_be, bool o, GncSqlObjectBackendPtr e) :
be{sql_be}, is_ok{o}, obe{e} {}
void commit (QofInstance* inst) {
if (is_ok) is_ok = obe->commit (be, inst);
}
GncSqlBackend* be;
bool is_ok;
GncSqlObjectBackendPtr obe;
};
/**
* Performs an operation on the database.
*

View File

@ -99,16 +99,9 @@ static EntryVec billterm_parent_col_table
bt_set_parent_guid),
};
class GncSqlBillTermBackend : public GncSqlObjectBackend
{
public:
GncSqlBillTermBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
GncSqlBillTermBackend::GncSqlBillTermBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_BILLTERM,
TABLE_NAME, col_table) {}
typedef struct
{
@ -358,12 +351,5 @@ GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::add_to_query(const GncSqlBackend* sq
{
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_billterm_sql_initialize (void)
{
static GncSqlBillTermBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_BILLTERM, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,11 +30,15 @@
#ifndef GNC_BILLTERM_SQL_H
#define GNC_BILLTERM_SQL_H
#include "gnc-backend-sql.h"
extern "C"
#include "gnc-sql-object-backend.hpp"
class GncSqlBillTermBackend : public GncSqlObjectBackend
{
#include "qof.h"
}
void gnc_billterm_sql_initialize (void);
public:
GncSqlBillTermBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_BILLTERM_SQL_H */

View File

@ -73,14 +73,9 @@ static const EntryVec col_table
set_root_template_guid)
};
class GncSqlBookBackend : public GncSqlObjectBackend
{
public:
GncSqlBookBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
};
GncSqlBookBackend::GncSqlBookBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_BOOK,
BOOK_TABLE, col_table) {}
/* ================================================================= */
static gpointer
@ -201,12 +196,4 @@ GncSqlBookBackend::load_all (GncSqlBackend* sql_be)
}
}
/* ================================================================= */
void
gnc_sql_init_book_handler (void)
{
static GncSqlBookBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_BOOK, BOOK_TABLE, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -29,11 +29,14 @@
#ifndef GNC_BOOK_SQL_H
#define GNC_BOOK_SQL_H
#include "gnc-backend-sql.h"
extern "C"
#include "gnc-sql-object-backend.hpp"
class GncSqlBookBackend : public GncSqlObjectBackend
{
#include "qof.h"
}
void gnc_sql_init_book_handler (void);
public:
GncSqlBookBackend();
void load_all(GncSqlBackend*) override;
};
#endif /* GNC_BOOK_SQL_H */

View File

@ -81,19 +81,9 @@ static void set_period_num (gpointer pObj, gpointer val);
static gnc_numeric get_amount (gpointer pObj);
static void set_amount (gpointer pObj, gnc_numeric value);
class GncSqlBudgetBackend : public GncSqlObjectBackend
{
public:
GncSqlBudgetBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
bool write(GncSqlBackend*) override;
private:
static void save(QofInstance*, void*);
};
GncSqlBudgetBackend::GncSqlBudgetBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_BUDGET,
BUDGET_TABLE, col_table) {}
typedef struct
{
@ -496,12 +486,5 @@ GncSqlColumnTableEntryImpl<CT_BUDGETREF>::add_to_query(const GncSqlBackend* sql_
{
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_sql_init_budget_handler (void)
{
static GncSqlBudgetBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_BUDGET, BUDGET_TABLE, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -29,6 +29,18 @@
#ifndef GNC_BUDGET_SQL_H
#define GNC_BUDGET_SQL_H
void gnc_sql_init_budget_handler (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlBudgetBackend : public GncSqlObjectBackend
{
public:
GncSqlBudgetBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
bool write(GncSqlBackend*) override;
private:
static void save(QofInstance*, void*);
};
#endif /* GNC_BUDGET_SQL_H */

View File

@ -88,16 +88,9 @@ static const EntryVec col_table
"quote_tz", COMMODITY_MAX_QUOTE_TZ_LEN, 0, "quote-tz"),
};
class GncSqlCommodityBackend : public GncSqlObjectBackend
{
public:
GncSqlCommodityBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override;
};
GncSqlCommodityBackend::GncSqlCommodityBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_COMMODITY,
COMMODITIES_TABLE, col_table) {}
/* ================================================================= */
static gpointer
@ -166,7 +159,7 @@ GncSqlCommodityBackend::load_all (GncSqlBackend* sql_be)
guid = *qof_instance_get_guid (QOF_INSTANCE (pCommodity));
pCommodity = gnc_commodity_table_insert (pTable, pCommodity);
if (qof_instance_is_dirty (QOF_INSTANCE (pCommodity)))
gnc_sql_push_commodity_for_postload_processing (sql_be, (gpointer)pCommodity);
sql_be->commodity_for_postload_processing(pCommodity);
qof_instance_set_guid (QOF_INSTANCE (pCommodity), &guid);
}
@ -292,13 +285,5 @@ GncSqlColumnTableEntryImpl<CT_COMMODITYREF>::add_to_query(const GncSqlBackend* s
{
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_sql_init_commodity_handler (void)
{
static GncSqlCommodityBackend be_data =
{
GNC_SQL_BACKEND_VERSION, GNC_ID_COMMODITY, COMMODITIES_TABLE, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -29,12 +29,23 @@
#ifndef GNC_COMMODITY_SQL_H
#define GNC_COMMODITY_SQL_H
#include "gnc-backend-sql.h"
#include "gnc-sql-backend.hpp"
#include "gnc-sql-object-backend.hpp"
extern "C"
{
#include "gnc-commodity.h"
}
void gnc_sql_init_commodity_handler (void);
class GncSqlCommodityBackend : public GncSqlObjectBackend
{
public:
GncSqlCommodityBackend();
void load_all(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override;
};
gboolean gnc_sql_save_commodity (GncSqlBackend* sql_be,
gnc_commodity* pCommodity);
void gnc_sql_commit_commodity (gnc_commodity* pCommodity);

View File

@ -94,16 +94,9 @@ static EntryVec col_table
(QofSetterFunc)gncCustomerSetTaxTable),
});
class GncSqlCustomerBackend : public GncSqlObjectBackend
{
public:
GncSqlCustomerBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
GncSqlCustomerBackend::GncSqlCustomerBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_CUSTOMER,
TABLE_NAME, col_table) {}
static GncCustomer*
load_single_customer (GncSqlBackend* sql_be, GncSqlRow& row)
@ -219,12 +212,4 @@ GncSqlCustomerBackend::write (GncSqlBackend* sql_be)
return data.is_ok;
}
/* ================================================================= */
void
gnc_customer_sql_initialize (void)
{
static GncSqlCustomerBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_CUSTOMER, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,6 +30,15 @@
#ifndef GNC_CUSTOMER_SQL_H
#define GNC_CUSTOMER_SQL_H
void gnc_customer_sql_initialize (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlCustomerBackend : public GncSqlObjectBackend
{
public:
GncSqlCustomerBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_CUSTOMER_SQL_H */

View File

@ -79,17 +79,9 @@ static EntryVec col_table
gnc_sql_make_table_entry<CT_ADDRESS>("addr", 0, 0, "address"),
});
class GncSqlEmployeeBackend : public GncSqlObjectBackend
{
public:
GncSqlEmployeeBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override;
bool write(GncSqlBackend*) override;
};
GncSqlEmployeeBackend::GncSqlEmployeeBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_EMPLOYEE,
TABLE_NAME, col_table) {}
static GncEmployee*
load_single_employee (GncSqlBackend* sql_be, GncSqlRow& row)
@ -264,12 +256,5 @@ GncSqlEmployeeBackend::write (GncSqlBackend* sql_be)
return data.is_ok;
}
/* ================================================================= */
void
gnc_employee_sql_initialize (void)
{
static GncSqlEmployeeBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_EMPLOYEE, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,6 +30,16 @@
#ifndef GNC_EMPLOYEE_SQL_H
#define GNC_EMPLOYEE_SQL_H
void gnc_employee_sql_initialize (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlEmployeeBackend : public GncSqlObjectBackend
{
public:
GncSqlEmployeeBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_EMPLOYEE_SQL_H */

View File

@ -129,16 +129,9 @@ static EntryVec col_table
(QofSetterFunc)gncEntrySetOrder),
});
class GncSqlEntryBackend : public GncSqlObjectBackend
{
public:
GncSqlEntryBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
GncSqlEntryBackend::GncSqlEntryBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_ENTRY,
TABLE_NAME, col_table) {}
static void
entry_set_invoice (gpointer pObject, gpointer val)
@ -274,12 +267,5 @@ GncSqlEntryBackend::write (GncSqlBackend* sql_be)
return data.is_ok;
}
/* ================================================================= */
void
gnc_entry_sql_initialize (void)
{
static GncSqlEntryBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_ENTRY, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,6 +30,15 @@
#ifndef GNC_ENTRY_SQL_H
#define GNC_ENTRY_SQL_H
void gnc_entry_sql_initialize (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlEntryBackend : public GncSqlObjectBackend
{
public:
GncSqlEntryBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_ENTRY_SQL_H */

View File

@ -101,17 +101,9 @@ static EntryVec col_table
(QofSetterFunc)gncInvoiceSetToChargeAmount),
});
class GncSqlInvoiceBackend : public GncSqlObjectBackend
{
public:
GncSqlInvoiceBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
bool write(GncSqlBackend*) override;
};
GncSqlInvoiceBackend::GncSqlInvoiceBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_INVOICE,
TABLE_NAME, col_table) {}
static GncInvoice*
load_single_invoice (GncSqlBackend* sql_be, GncSqlRow& row)
@ -313,12 +305,4 @@ GncSqlColumnTableEntryImpl<CT_INVOICEREF>::add_to_query(const GncSqlBackend* sql
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_invoice_sql_initialize (void)
{
static GncSqlInvoiceBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_INVOICE, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,6 +30,16 @@
#ifndef GNC_INVOICE_SQL_H
#define GNC_INVOICE_SQL_H
void gnc_invoice_sql_initialize (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlInvoiceBackend : public GncSqlObjectBackend
{
public:
GncSqlInvoiceBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_INVOICE_SQL_H */

View File

@ -73,16 +73,9 @@ static EntryVec col_table
(QofSetterFunc)gncJobSetOwner),
});
class GncSqlJobBackend : public GncSqlObjectBackend
{
public:
GncSqlJobBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
GncSqlJobBackend::GncSqlJobBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_JOB,
TABLE_NAME, col_table) {}
static GncJob*
load_single_job (GncSqlBackend* sql_be, GncSqlRow& row)
@ -170,12 +163,4 @@ GncSqlJobBackend::write (GncSqlBackend* sql_be)
return data.is_ok;
}
/* ================================================================= */
void
gnc_job_sql_initialize (void)
{
static GncSqlJobBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_JOB, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,6 +30,14 @@
#ifndef GNC_JOB_SQL_H
#define GNC_JOB_SQL_H
void gnc_job_sql_initialize (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlJobBackend : public GncSqlObjectBackend
{
public:
GncSqlJobBackend();
void load_all(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_JOB_SQL_H */

View File

@ -68,16 +68,9 @@ static const EntryVec col_table
gnc_sql_make_table_entry<CT_BOOLEAN>("is_closed", 0, COL_NNUL, "is-closed")
});
class GncSqlLotsBackend : public GncSqlObjectBackend
{
public:
GncSqlLotsBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
GncSqlLotsBackend::GncSqlLotsBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_LOT,
TABLE_NAME, col_table) {}
/* ================================================================= */
static gpointer
@ -229,13 +222,5 @@ GncSqlColumnTableEntryImpl<CT_LOTREF>::add_to_query(const GncSqlBackend* sql_be,
{
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_sql_init_lot_handler (void)
{
static GncSqlLotsBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_LOT, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -29,6 +29,15 @@
#ifndef GNC_LOT_SQL_H
#define GNC_LOT_SQL_H
void gnc_sql_init_lot_handler (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlLotsBackend : public GncSqlObjectBackend
{
public:
GncSqlLotsBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_LOT_SQL_H */

View File

@ -75,15 +75,9 @@ static EntryVec col_table
ORDER_OWNER, true),
});
class GncSqlOrderBackend : public GncSqlObjectBackend
{
public:
GncSqlOrderBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
GncSqlOrderBackend::GncSqlOrderBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_ORDER,
TABLE_NAME, col_table) {}
static GncOrder*
load_single_order (GncSqlBackend* sql_be, GncSqlRow& row)
@ -199,13 +193,5 @@ GncSqlColumnTableEntryImpl<CT_ORDERREF>::add_to_query(const GncSqlBackend* sql_b
{
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_order_sql_initialize (void)
{
static GncSqlOrderBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_ORDER, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,6 +30,14 @@
#ifndef GNC_ORDER_SQL_H
#define GNC_ORDER_SQL_H
void gnc_order_sql_initialize (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlOrderBackend : public GncSqlObjectBackend
{
public:
GncSqlOrderBackend();
void load_all(GncSqlBackend*) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_ORDER_SQL_H */

View File

@ -71,18 +71,9 @@ static const EntryVec col_table
gnc_sql_make_table_entry<CT_NUMERIC>("value", 0, COL_NNUL, "value")
});
class GncSqlPriceBackend : public GncSqlObjectBackend
{
public:
GncSqlPriceBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
bool write(GncSqlBackend*) override;
};
GncSqlPriceBackend::GncSqlPriceBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_PRICE,
TABLE_NAME, col_table) {}
/* ================================================================= */
@ -236,13 +227,4 @@ GncSqlPriceBackend::write (GncSqlBackend* sql_be)
return gnc_pricedb_foreach_price (priceDB, write_price, &data, TRUE);
}
/* ================================================================= */
void
gnc_sql_init_price_handler (void)
{
static GncSqlPriceBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_PRICE, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -29,6 +29,16 @@
#ifndef GNC_PRICE_SQL_H
#define GNC_PRICE_SQL_H
void gnc_sql_init_price_handler (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlPriceBackend : public GncSqlObjectBackend
{
public:
GncSqlPriceBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_PRICE_SQL_H */

View File

@ -117,16 +117,8 @@ static const EntryVec weekend_adjust_col_table
* Recurrences are neither loadable nor committable. Note that the default
* write() implementation is also a no-op.
*/
class GncSqlRecurrenceBackend : public GncSqlObjectBackend
{
public:
GncSqlRecurrenceBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override { return; }
void create_tables(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override { return false; }
};
GncSqlRecurrenceBackend::GncSqlRecurrenceBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_ACCOUNT, TABLE_NAME, col_table) {}
/* ================================================================= */
@ -434,12 +426,4 @@ GncSqlRecurrenceBackend::create_tables (GncSqlBackend* sql_be)
}
}
/* ================================================================= */
void
gnc_sql_init_recurrence_handler (void)
{
static GncSqlRecurrenceBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_ACCOUNT, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -34,7 +34,16 @@ extern "C"
#include "Recurrence.h"
#include "guid.h"
}
#include "gnc-backend-sql.h"
#include "gnc-sql-object-backend.hpp"
class GncSqlRecurrenceBackend : public GncSqlObjectBackend
{
public:
GncSqlRecurrenceBackend();
void load_all(GncSqlBackend*) override { return; }
void create_tables(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override { return false; }
};
gboolean gnc_sql_recurrence_save (GncSqlBackend* sql_be, const GncGUID* guid,
const Recurrence* pRecurrence);
@ -44,6 +53,4 @@ gboolean gnc_sql_recurrence_delete (GncSqlBackend* sql_be, const GncGUID* guid);
Recurrence* gnc_sql_recurrence_load (GncSqlBackend* sql_be, const GncGUID* guid);
GList* gnc_sql_recurrence_load_list (GncSqlBackend* sql_be, const GncGUID* guid);
void gnc_sql_init_recurrence_handler (void);
#endif /* GNC_RECURRENCE_SQL_H */

View File

@ -85,15 +85,9 @@ static const EntryVec col_table
"template_act_guid", 0, COL_NNUL, "template-account"),
});
class GncSqlSchedXactionBackend : public GncSqlObjectBackend
{
public:
GncSqlSchedXactionBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
};
GncSqlSchedXactionBackend::GncSqlSchedXactionBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_SCHEDXACTION,
SCHEDXACTION_TABLE, col_table) {}
/* ================================================================= */
static SchedXaction*
@ -210,13 +204,4 @@ GncSqlSchedXactionBackend::commit (GncSqlBackend* sql_be, QofInstance* inst)
return is_ok;
}
/* ================================================================= */
void
gnc_sql_init_schedxaction_handler (void)
{
static GncSqlSchedXactionBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_SCHEDXACTION, SCHEDXACTION_TABLE,
col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -32,9 +32,16 @@ extern "C"
{
#include "qof.h"
}
#include "gnc-backend-sql.h"
#include "gnc-sql-object-backend.hpp"
class GncSqlSchedXactionBackend : public GncSqlObjectBackend
{
public:
GncSqlSchedXactionBackend();
void load_all(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
};
void gnc_sql_init_schedxaction_handler (void);
gboolean gnc_sql_save_schedxaction (GncSqlBackend* sql_be, QofInstance* inst);
#endif /* GNC_SCHEDXACTION_SQL_H */

View File

@ -165,20 +165,9 @@ static const EntryVec gdate_col_table
gnc_sql_make_table_entry<CT_GDATE>("gdate_val", 0, 0),
};
/**
* Slots are neither loadable nor committable. Note that the default
* write() implementation is also a no-op.
*/
class GncSqlSlotsBackend : public GncSqlObjectBackend
{
public:
GncSqlSlotsBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override { return; }
void create_tables(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override { return false; }
};
GncSqlSlotsBackend::GncSqlSlotsBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_ACCOUNT,
TABLE_NAME, col_table) {}
/* ================================================================= */
@ -1044,13 +1033,4 @@ GncSqlSlotsBackend::create_tables (GncSqlBackend* sql_be)
}
}
/* ================================================================= */
void
gnc_sql_init_slots_handler (void)
{
static GncSqlSlotsBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_ACCOUNT, TABLE_NAME, col_table};
gnc_sql_register_backend(std::make_tuple(std::string{TABLE_NAME},
&be_data));
}
/* ========================== END OF FILE ===================== */

View File

@ -34,7 +34,20 @@ extern "C"
#include "guid.h"
#include "qof.h"
}
#include "gnc-backend-sql.h"
#include "gnc-sql-object-backend.hpp"
/**
* Slots are neither loadable nor committable. Note that the default
* write() implementation is also a no-op.
*/
class GncSqlSlotsBackend : public GncSqlObjectBackend
{
public:
GncSqlSlotsBackend();
void load_all(GncSqlBackend*) override { return; }
void create_tables(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override { return false; }
};
/**
* gnc_sql_slots_save - Saves slots for an object to the db.

View File

@ -24,9 +24,18 @@ extern "C"
{
#include <config.h>
#include <gnc-prefs.h>
#include <gnc-engine.h>
#include <gnc-commodity.h>
#include <SX-book.h>
#include <Recurrence.h>
#include <gncBillTerm.h>
#include <gncTaxTable.h>
#include <gncInvoice.h>
#include <gnc-pricedb.h>
}
#include <algorithm>
#include <cassert>
#include "gnc-sql-connection.hpp"
#include "gnc-sql-backend.hpp"
@ -35,6 +44,27 @@ extern "C"
#include "gnc-sql-result.hpp"
#include "gnc-backend-sql.h"
#include "gnc-account-sql.h"
#include "gnc-book-sql.h"
#include "gnc-budget-sql.h"
#include "gnc-commodity-sql.h"
#include "gnc-lots-sql.h"
#include "gnc-price-sql.h"
#include "gnc-recurrence-sql.h"
#include "gnc-schedxaction-sql.h"
#include "gnc-slots-sql.h"
#include "gnc-transaction-sql.h"
#include "gnc-bill-term-sql.h"
#include "gnc-customer-sql.h"
#include "gnc-employee-sql.h"
#include "gnc-entry-sql.h"
#include "gnc-invoice-sql.h"
#include "gnc-job-sql.h"
#include "gnc-order-sql.h"
#include "gnc-tax-table-sql.h"
#include "gnc-vendor-sql.h"
static QofLogModule log_module = G_LOG_DOMAIN;
#define VERSION_TABLE_NAME "versions"
#define MAX_TABLE_NAME_LEN 50
@ -169,6 +199,439 @@ GncSqlBackend::finish_progress() const noexcept
(qof_be.percentage) (nullptr, -1.0);
}
void
GncSqlBackend::create_tables() noexcept
{
for(auto entry : m_backend_registry)
{
update_progress();
std::get<1>(entry)->create_tables(this);
}
}
/* Main object load order */
static const StrVec fixed_load_order
{ GNC_ID_BOOK, GNC_ID_COMMODITY, GNC_ID_ACCOUNT, GNC_ID_LOT };
/* Order in which business objects need to be loaded */
static const StrVec business_fixed_load_order =
{ GNC_ID_BILLTERM, GNC_ID_TAXTABLE, GNC_ID_INVOICE };
void
GncSqlBackend::ObjectBackendRegistry::load_remaining(GncSqlBackend* sql_be)
{
for (auto entry : m_registry)
{
std::string type;
GncSqlObjectBackendPtr obe = nullptr;
std::tie(type, obe) = entry;
if (!obe->is_version(GNC_SQL_BACKEND_VERSION)) continue;
/* Don't need to load anything if it has already been loaded with
* the fixed order.
*/
if (std::find(fixed_load_order.begin(), fixed_load_order.end(),
type) != fixed_load_order.end()) continue;
if (std::find(business_fixed_load_order.begin(),
business_fixed_load_order.end(),
type) != business_fixed_load_order.end()) continue;
obe->load_all (sql_be);
}
}
typedef struct
{
QofIdType searchObj;
gpointer pCompiledQuery;
} gnc_sql_query_info;
/* callback structure */
typedef struct
{
gboolean is_known;
gboolean is_ok;
GncSqlBackend* sql_be;
QofInstance* inst;
QofQuery* pQuery;
gpointer pCompiledQuery;
gnc_sql_query_info* pQueryInfo;
} sql_backend;
void
GncSqlBackend::load (QofBook* book, QofBackendLoadType loadType)
{
Account* root;
g_return_if_fail (book != NULL);
ENTER ("sql_be=%p, book=%p", this, book);
m_loading = TRUE;
if (loadType == LOAD_TYPE_INITIAL_LOAD)
{
assert (m_book == nullptr);
m_book = book;
/* Load any initial stuff. Some of this needs to happen in a certain order */
for (auto type : fixed_load_order)
{
auto obe = m_backend_registry.get_object_backend(type);
if (obe)
{
update_progress();
obe->load_all(this);
}
}
for (auto type : business_fixed_load_order)
{
auto obe = m_backend_registry.get_object_backend(type);
if (obe)
{
update_progress();
obe->load_all(this);
}
}
root = gnc_book_get_root_account( book );
gnc_account_foreach_descendant(root, (AccountCb)xaccAccountBeginEdit,
nullptr);
m_backend_registry.load_remaining(this);
gnc_account_foreach_descendant(root, (AccountCb)xaccAccountCommitEdit,
nullptr);
}
else if (loadType == LOAD_TYPE_LOAD_ALL)
{
// Load all transactions
auto obe = m_backend_registry.get_object_backend (GNC_ID_TRANS);
obe->load_all (this);
}
m_loading = FALSE;
std::for_each(m_postload_commodities.begin(), m_postload_commodities.end(),
[](gnc_commodity* comm) { gnc_sql_commit_commodity (comm); });
m_postload_commodities.empty();
/* Mark the sessoion as clean -- though it should never be marked
* dirty with this backend
*/
qof_book_mark_session_saved (book);
finish_progress();
LEAVE ("");
}
/* ================================================================= */
bool
GncSqlBackend::write_account_tree(Account* root)
{
GList* descendants;
GList* node;
bool is_ok = true;
g_return_val_if_fail (root != nullptr, false);
auto obe = m_backend_registry.get_object_backend(GNC_ID_ACCOUNT);
is_ok = obe->commit (this, QOF_INSTANCE (root));
if (is_ok)
{
descendants = gnc_account_get_descendants (root);
for (node = descendants; node != NULL && is_ok; node = g_list_next (node))
{
is_ok = obe->commit(this, QOF_INSTANCE (GNC_ACCOUNT (node->data)));
if (!is_ok) break;
}
g_list_free (descendants);
}
update_progress();
return is_ok;
}
bool
GncSqlBackend::write_accounts()
{
update_progress();
auto is_ok = write_account_tree (gnc_book_get_root_account (m_book));
if (is_ok)
{
update_progress();
is_ok = write_account_tree (gnc_book_get_template_root(m_book));
}
return is_ok;
}
static gboolean // Can't be bool because of signature for xaccAccountTreeForEach
write_tx (Transaction* tx, gpointer data)
{
auto s = static_cast<write_objects_t*>(data);
g_return_val_if_fail (tx != NULL, 0);
g_return_val_if_fail (data != NULL, 0);
s->commit (QOF_INSTANCE (tx));
auto splitbe = s->be->get_object_backend(GNC_ID_SPLIT);
for (auto split_node = xaccTransGetSplitList (tx);
split_node != nullptr && s->is_ok;
split_node = g_list_next (split_node))
{
s->is_ok = splitbe->commit(s->be, QOF_INSTANCE(split_node->data));
}
s->be->update_progress ();
return (s->is_ok ? 0 : 1);
}
bool
GncSqlBackend::write_transactions()
{
auto obe = m_backend_registry.get_object_backend(GNC_ID_TRANS);
write_objects_t data{this, TRUE, obe.get()};
(void)xaccAccountTreeForEachTransaction (
gnc_book_get_root_account (m_book), write_tx, &data);
update_progress();
return data.is_ok;
}
bool
GncSqlBackend::write_template_transactions()
{
auto obe = m_backend_registry.get_object_backend(GNC_ID_TRANS);
write_objects_t data{this, true, obe.get()};
auto ra = gnc_book_get_template_root (m_book);
if (gnc_account_n_descendants (ra) > 0)
{
(void)xaccAccountTreeForEachTransaction (ra, write_tx, &data);
update_progress();
}
return data.is_ok;
}
bool
GncSqlBackend::write_schedXactions()
{
GList* schedXactions;
SchedXaction* tmpSX;
bool is_ok = true;
schedXactions = gnc_book_get_schedxactions (m_book)->sx_list;
auto obe = m_backend_registry.get_object_backend(GNC_ID_SCHEDXACTION);
for (; schedXactions != NULL && is_ok; schedXactions = schedXactions->next)
{
tmpSX = static_cast<decltype (tmpSX)> (schedXactions->data);
is_ok = obe->commit (this, QOF_INSTANCE (tmpSX));
}
update_progress();
return is_ok;
}
#pragma GCC diagnostic warning "-Wformat-nonliteral"
void
GncSqlBackend::sync_all(QofBook* book)
{
g_return_if_fail (book != NULL);
reset_version_info();
ENTER ("book=%p, sql_be->book=%p", book, m_book);
update_progress();
/* Create new tables */
m_is_pristine_db = true;
create_tables();
/* Save all contents */
m_book = book;
auto is_ok = m_conn->begin_transaction();
// FIXME: should write the set of commodities that are used
// write_commodities(sql_be, book);
if (is_ok)
{
auto obe = m_backend_registry.get_object_backend(GNC_ID_BOOK);
is_ok = obe->commit (this, QOF_INSTANCE (book));
}
if (is_ok)
{
is_ok = write_accounts();
}
if (is_ok)
{
is_ok = write_transactions();
}
if (is_ok)
{
is_ok = write_template_transactions();
}
if (is_ok)
{
is_ok = write_schedXactions();
}
if (is_ok)
{
for (auto entry : m_backend_registry)
std::get<1>(entry)->write (this);
}
if (is_ok)
{
is_ok = m_conn->commit_transaction();
}
if (is_ok)
{
m_is_pristine_db = false;
/* Mark the session as clean -- though it shouldn't ever get
* marked dirty with this backend
*/
qof_book_mark_session_saved(book);
}
else
{
if (!qof_backend_check_error (&qof_be))
qof_backend_set_error (&qof_be, ERR_BACKEND_SERVER_ERR);
is_ok = m_conn->rollback_transaction ();
}
finish_progress();
LEAVE ("book=%p", book);
}
/* ================================================================= */
/* Routines to deal with the creation of multiple books. */
void
GncSqlBackend::begin_edit (QofInstance* inst)
{
g_return_if_fail (inst != NULL);
ENTER (" ");
LEAVE ("");
}
void
GncSqlBackend::rollback_edit(QofInstance* inst)
{
g_return_if_fail (inst != NULL);
ENTER (" ");
LEAVE ("");
}
void
GncSqlBackend::commodity_for_postload_processing(gnc_commodity* commodity)
{
m_postload_commodities.push_back(commodity);
}
GncSqlObjectBackendPtr
GncSqlBackend::get_object_backend(const std::string& type) const noexcept
{
return m_backend_registry.get_object_backend(type);
}
/* Commit_edit handler - find the correct backend handler for this object
* type and call its commit handler
*/
void
GncSqlBackend::commit_edit (QofInstance* inst)
{
sql_backend be_data;
gboolean is_dirty;
gboolean is_destroying;
gboolean is_infant;
g_return_if_fail (inst != NULL);
if (qof_book_is_readonly(m_book))
{
qof_backend_set_error (&qof_be, ERR_BACKEND_READONLY);
(void)m_conn->rollback_transaction ();
return;
}
/* During initial load where objects are being created, don't commit
anything, but do mark the object as clean. */
if (m_loading)
{
qof_instance_mark_clean (inst);
return;
}
// The engine has a PriceDB object but it isn't in the database
if (strcmp (inst->e_type, "PriceDB") == 0)
{
qof_instance_mark_clean (inst);
qof_book_mark_session_saved (m_book);
return;
}
ENTER (" ");
is_dirty = qof_instance_get_dirty_flag (inst);
is_destroying = qof_instance_get_destroying (inst);
is_infant = qof_instance_get_infant (inst);
DEBUG ("%s dirty = %d, do_free = %d, infant = %d\n",
(inst->e_type ? inst->e_type : "(null)"),
is_dirty, is_destroying, is_infant);
if (!is_dirty && !is_destroying)
{
LEAVE ("!dirty OR !destroying");
return;
}
if (!m_conn->begin_transaction ())
{
PERR ("begin_transaction failed\n");
LEAVE ("Rolled back - database transaction begin error");
return;
}
bool is_ok = true;
auto obe = m_backend_registry.get_object_backend(std::string{inst->e_type});
if (obe != nullptr)
is_ok = obe->commit(this, inst);
else
{
PERR ("Unknown object type '%s'\n", inst->e_type);
(void)m_conn->rollback_transaction ();
// Don't let unknown items still mark the book as being dirty
qof_book_mark_session_saved(m_book);
qof_instance_mark_clean (inst);
LEAVE ("Rolled back - unknown object type");
return;
}
if (!is_ok)
{
// Error - roll it back
(void)m_conn->rollback_transaction();
// This *should* leave things marked dirty
LEAVE ("Rolled back - database error");
return;
}
(void)m_conn->commit_transaction ();
qof_book_mark_session_saved(m_book);
qof_instance_mark_clean (inst);
LEAVE ("");
}
/**
* Sees if the version table exists, and if it does, loads the info into
* the version hash table. Otherwise, it creates an empty version table.
@ -338,3 +801,52 @@ GncSqlBackend::time64_to_string (time64 t) const noexcept
g_free(datebuf);
return date;
}
GncSqlBackend::ObjectBackendRegistry::ObjectBackendRegistry()
{
register_backend(std::make_shared<GncSqlBookBackend>());
register_backend(std::make_shared<GncSqlCommodityBackend>());
register_backend(std::make_shared<GncSqlAccountBackend>());
register_backend(std::make_shared<GncSqlBudgetBackend>());
register_backend(std::make_shared<GncSqlPriceBackend>());
register_backend(std::make_shared<GncSqlTransBackend>());
register_backend(std::make_shared<GncSqlSplitBackend>());
register_backend(std::make_shared<GncSqlSlotsBackend>());
register_backend(std::make_shared<GncSqlRecurrenceBackend>());
register_backend(std::make_shared<GncSqlSchedXactionBackend>());
register_backend(std::make_shared<GncSqlLotsBackend>());
register_backend(std::make_shared<GncSqlBillTermBackend>());
register_backend(std::make_shared<GncSqlCustomerBackend>());
register_backend(std::make_shared<GncSqlEmployeeBackend>());
register_backend(std::make_shared<GncSqlEntryBackend>());
register_backend(std::make_shared<GncSqlInvoiceBackend>());
register_backend(std::make_shared<GncSqlJobBackend>());
register_backend(std::make_shared<GncSqlOrderBackend>());
register_backend(std::make_shared<GncSqlTaxTableBackend>());
register_backend(std::make_shared<GncSqlVendorBackend>());
}
void
GncSqlBackend::ObjectBackendRegistry::register_backend(OBEEntry&& entry) noexcept
{
m_registry.emplace_back(entry);
}
void
GncSqlBackend::ObjectBackendRegistry::register_backend(GncSqlObjectBackendPtr obe) noexcept
{
m_registry.emplace_back(make_tuple(std::string{obe->type()}, obe));
}
GncSqlObjectBackendPtr
GncSqlBackend::ObjectBackendRegistry::get_object_backend(const std::string& type) const
{
auto entry = std::find_if(m_registry.begin(), m_registry.end(),
[type](const OBEEntry& entry){
return type == std::get<0>(entry);
});
if (entry == m_registry.end())
return nullptr;
return std::get<1>(*entry);
}

View File

@ -38,7 +38,7 @@ class GncSqlColumnTableEntry;
using GncSqlColumnTableEntryPtr = std::shared_ptr<GncSqlColumnTableEntry>;
using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
class GncSqlObjectBackend;
using GncSqlObjectBackendPtr = GncSqlObjectBackend*;
using GncSqlObjectBackendPtr = std::shared_ptr<GncSqlObjectBackend>;
using OBEEntry = std::tuple<std::string, GncSqlObjectBackendPtr>;
using OBEVec = std::vector<OBEEntry>;
class GncSqlConnection;
@ -157,17 +157,58 @@ public:
* @return String representation of the Timespec
*/
std::string time64_to_string (time64 t) const noexcept;
/**
* Load the contents of an SQL database into a book.
*
* @param book Book to be loaded
*/
void load(QofBook*, QofBackendLoadType);
/**
* Save the contents of a book to an SQL database.
*
* @param book Book to be saved
*/
void sync_all(QofBook*);
/**
* An object is about to be edited.
*
* @param inst Object being edited
*/
void begin_edit(QofInstance*);
/**
* Object editting is complete and the object should be saved.
*
* @param inst Object being edited
*/
void commit_edit(QofInstance*);
/**
* Object editing has been cancelled.
*
* @param inst Object being edited
*/
void rollback_edit(QofInstance*);
/**
* 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;
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() const noexcept;
void finish_progress() const noexcept;
friend void gnc_sql_load (GncSqlBackend* sql_be, QofBook* book, QofBackendLoadType loadType);
friend void gnc_sql_sync_all (GncSqlBackend* sql_be, QofBook* book);
friend void gnc_sql_commit_edit (GncSqlBackend* sql_be, QofInstance* inst);
protected:
protected:
QofBackend qof_be; /**< QOF backend. Not a pointer, nor really a member */
GncSqlConnection* m_conn; /**< SQL connection */
QofBook* m_book; /**< The primary, main open book */
@ -176,6 +217,32 @@ public:
bool m_is_pristine_db; /**< Are we saving to a new pristine db? */
const char* m_timespec_format; /**< 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();
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(); }
private:
OBEVec m_registry;
};
ObjectBackendRegistry m_backend_registry;
std::vector<gnc_commodity*> m_postload_commodities;
};
#endif //__GNC_SQL_BACKEND_HPP__

View File

@ -29,6 +29,7 @@ extern "C"
#include "gnc-sql-backend.hpp"
#include "gnc-sql-column-table-entry.hpp"
#include "gnc-slots-sql.h"
#include "gnc-backend-sql.h" //for gnc_sql_do_db_operation
static QofLogModule log_module = G_LOG_DOMAIN;

View File

@ -36,6 +36,7 @@ class GncSqlBackend;
class GncSqlColumnTableEntry;
using GncSqlColumnTableEntryPtr = std::shared_ptr<GncSqlColumnTableEntry>;
using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
using InstanceVec = std::vector<QofInstance*>;
typedef enum
{
@ -108,9 +109,29 @@ protected:
const EntryVec& m_col_table; /// The ORM table definition.
};
using GncSqlObjectBackendPtr = GncSqlObjectBackend*;
using GncSqlObjectBackendPtr = std::shared_ptr<GncSqlObjectBackend>;
using OBEEntry = std::tuple<std::string, GncSqlObjectBackendPtr>;
using OBEVec = std::vector<OBEEntry>;
/**
* Data-passing struct for callbacks to qof_object_foreach() used in
* GncSqlObjectBackend::write(). Once QofCollection is rewritten to use C++
* containers we'll use std::foreach() and lambdas instead of callbacks and this
* can go away.
*/
struct write_objects_t
{
write_objects_t() = default;
write_objects_t (GncSqlBackend* sql_be, bool o, GncSqlObjectBackend* e) :
be{sql_be}, is_ok{o}, obe{e} {}
void commit (QofInstance* inst) {
if (is_ok) is_ok = obe->commit (be, inst);
}
GncSqlBackend* be;
bool is_ok;
GncSqlObjectBackend* obe;
};
#endif //__GNC_SQL_OBJECT_BACKEND_HPP__

View File

@ -117,17 +117,9 @@ static EntryVec guid_col_table
get_obj_guid, set_obj_guid),
});
class GncSqlTaxTableBackend : public GncSqlObjectBackend
{
public:
GncSqlTaxTableBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
bool write(GncSqlBackend*) override;
};
GncSqlTaxTableBackend::GncSqlTaxTableBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_TAXTABLE,
TT_TABLE_NAME, tt_col_table) {}
typedef struct
{
@ -517,12 +509,4 @@ GncSqlColumnTableEntryImpl<CT_TAXTABLEREF>::add_to_query(const GncSqlBackend* sq
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_taxtable_sql_initialize (void)
{
static GncSqlTaxTableBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_TAXTABLE, TT_TABLE_NAME, tt_col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,6 +30,16 @@
#ifndef GNC_TAXTABLE_SQL_H
#define GNC_TAXTABLE_SQL_H
void gnc_taxtable_sql_initialize (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlTaxTableBackend : public GncSqlObjectBackend
{
public:
GncSqlTaxTableBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_TAXTABLE_SQL_H */

View File

@ -74,7 +74,7 @@ struct split_info_t : public write_objects_t
{
split_info_t () = default;
split_info_t (GncSqlBackend* sql_be, bool o,
GncSqlObjectBackendPtr e, const GncGUID* g):
GncSqlObjectBackend* e, const GncGUID* g):
write_objects_t(sql_be, o, e), guid{g} {}
const GncGUID* guid;
};
@ -139,29 +139,14 @@ static const EntryVec tx_guid_col_table
gnc_sql_make_table_entry<CT_GUID>("tx_guid", 0, 0, "guid"),
};
class GncSqlTransBackend : public GncSqlObjectBackend
{
public:
GncSqlTransBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
};
GncSqlTransBackend::GncSqlTransBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_TRANS,
TRANSACTION_TABLE, tx_col_table) {}
GncSqlSplitBackend::GncSqlSplitBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_SPLIT,
SPLIT_TABLE, split_col_table) {}
class GncSqlSplitBackend : public GncSqlObjectBackend
{
public:
GncSqlSplitBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override { return; } // loaded by transaction.
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
};
static GncSqlSplitBackend be_data_split {
GNC_SQL_BACKEND_VERSION, GNC_ID_SPLIT, SPLIT_TABLE, split_col_table};
/* These functions exist but have not been tested.
#if LOAD_TRANSACTIONS_AS_NEEDED
compile_split_query,
@ -1413,14 +1398,4 @@ GncSqlColumnTableEntryImpl<CT_TXREF>::add_to_query(const GncSqlBackend* sql_be,
add_objectref_guid_to_query(sql_be, obj_name, pObject, vec);
}
/* ================================================================= */
void
gnc_sql_init_transaction_handler (void)
{
static GncSqlTransBackend be_data_tx {
GNC_SQL_BACKEND_VERSION, GNC_ID_TRANS, TRANSACTION_TABLE, tx_col_table};
gnc_sql_register_backend(&be_data_tx);
gnc_sql_register_backend(&be_data_split);
}
/* ========================== END OF FILE ===================== */

View File

@ -36,7 +36,23 @@ extern "C"
#include "qof.h"
#include "Account.h"
}
void gnc_sql_init_transaction_handler (void);
class GncSqlTransBackend : public GncSqlObjectBackend
{
public:
GncSqlTransBackend();
void load_all(GncSqlBackend*) override;
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
};
class GncSqlSplitBackend : public GncSqlObjectBackend
{
public:
GncSqlSplitBackend();
void load_all(GncSqlBackend*) override { return; } // loaded by transaction.
void create_tables(GncSqlBackend*) override;
bool commit (GncSqlBackend* sql_be, QofInstance* inst) override;
};
/**
* Loads all transactions which have splits for a specific account.

View File

@ -83,16 +83,9 @@ static EntryVec col_table
gnc_sql_make_table_entry<CT_TAXTABLEREF>("tax_table", 0, 0, "tax-table"),
});
class GncSqlVendorBackend : public GncSqlObjectBackend
{
public:
GncSqlVendorBackend(int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
GncSqlObjectBackend(version, type, table, vec) {}
void load_all(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override;
bool write(GncSqlBackend*) override;
};
GncSqlVendorBackend::GncSqlVendorBackend() :
GncSqlObjectBackend(GNC_SQL_BACKEND_VERSION, GNC_ID_VENDOR,
TABLE_NAME, col_table) {}
static GncVendor*
load_single_vendor (GncSqlBackend* sql_be, GncSqlRow& row)
@ -237,13 +230,4 @@ GncSqlVendorBackend::write (GncSqlBackend* sql_be)
return data.is_ok;
}
/* ================================================================= */
void
gnc_vendor_sql_initialize (void)
{
static GncSqlVendorBackend be_data {
GNC_SQL_BACKEND_VERSION, GNC_ID_VENDOR, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */

View File

@ -30,6 +30,16 @@
#ifndef GNC_VENDOR_SQL_H
#define GNC_VENDOR_SQL_H
void gnc_vendor_sql_initialize (void);
#include "gnc-sql-object-backend.hpp"
class GncSqlVendorBackend : public GncSqlObjectBackend
{
public:
GncSqlVendorBackend();
void load_all(GncSqlBackend*) override;
bool commit(GncSqlBackend*, QofInstance*) override;
bool write(GncSqlBackend*) override;
};
#endif /* GNC_VENDOR_SQL_H */

View File

@ -39,7 +39,6 @@ int main (int argc, char** argv)
{
qof_init ();
cashobjects_register ();
gnc_sql_init (NULL);
/* do_test(
qof_load_backend_library ("../.libs/", GNC_LIB_NAME),
" loading gnc-backend-gda GModule failed");

View File

@ -266,22 +266,16 @@ test_gnc_sql_commit_edit (void)
guint dirty_called = 0;
GncMockSqlConnection conn;
const char* msg1 =
"[gnc_sql_commit_edit()] gnc_sql_commit_edit(): Unknown object type 'null'\n";
const char* msg2 =
"[gnc_sql_commit_edit()] gnc_sql_commit_edit(): Unknown object type 'Book'\n";
"[GncSqlBackend::commit_edit()] Unknown object type 'null'\n";
GLogLevelFlags loglevel = static_cast<decltype (loglevel)>
(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
const char* logdomain = "gnc.backend.sql";
TestErrorStruct check1 = { loglevel, const_cast<char*> (logdomain),
const_cast<char*> (msg1), 0
};
TestErrorStruct check2 = { loglevel, const_cast<char*> (logdomain),
const_cast<char*> (msg2), 0
};
guint hdlr1;
test_add_error (&check1);
test_add_error (&check2);
hdlr1 = g_log_set_handler (logdomain, loglevel,
(GLogFunc)test_list_handler, NULL);
g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_handler, NULL);
@ -298,36 +292,33 @@ test_gnc_sql_commit_edit (void)
g_assert (qof_instance_get_dirty_flag (inst));
g_assert (qof_book_session_not_saved (book));
g_assert_cmpint (dirty_called, == , 1);
gnc_sql_commit_edit (&sql_be, inst);
sql_be.commit_edit (inst);
g_assert (!qof_instance_get_dirty_flag (inst));
g_assert (!qof_book_session_not_saved (book));
g_assert_cmpint (dirty_called, == , 0);
g_assert_cmpint (check1.hits, == , 2);
g_assert_cmpint (check2.hits, == , 0);
qof_book_mark_session_dirty (book);
g_assert (!qof_instance_get_dirty_flag (QOF_INSTANCE (book)));
g_assert (qof_book_session_not_saved (book));
g_assert_cmpint (dirty_called, == , 1);
gnc_sql_commit_edit (&sql_be, QOF_INSTANCE (book));
sql_be.commit_edit (QOF_INSTANCE (book));
g_assert (!qof_instance_get_dirty_flag (QOF_INSTANCE (book)));
g_assert (qof_book_session_not_saved (book));
g_assert_cmpint (dirty_called, == , 1);
g_assert_cmpint (check1.hits, == , 2);
g_assert_cmpint (check2.hits, == , 0);
qof_instance_set_dirty_flag (QOF_INSTANCE (book), TRUE);
g_assert (qof_instance_get_dirty_flag (QOF_INSTANCE (book)));
g_assert (qof_book_session_not_saved (book));
g_assert_cmpint (dirty_called, == , 1);
gnc_sql_commit_edit (&sql_be, QOF_INSTANCE (book));
sql_be.commit_edit(QOF_INSTANCE (book));
g_assert (!qof_instance_get_dirty_flag (QOF_INSTANCE (book)));
g_assert (!qof_book_session_not_saved (book));
g_assert_cmpint (dirty_called, == , 0);
g_assert_cmpint (check1.hits, == , 2);
g_assert_cmpint (check2.hits, == , 2);
g_log_remove_handler (logdomain, hdlr1);
g_object_unref (inst);