mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-12-01 21:19:16 -06:00
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:
parent
b2a644c29d
commit
ee0e61a07e
@ -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)
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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);
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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__
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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.
|
||||
|
@ -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 ===================== */
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user