mirror of
https://github.com/Gnucash/gnucash.git
synced 2026-09-03 20:53:02 -05:00
Replace qof_object_foo_backend with c++ native containers.
Since C++ provides find and for_each on native containers there's no need for a hand-rolled version in libqof.
This commit is contained in:
@@ -289,17 +289,16 @@ gnc_dbi_verify_conn (GncDbiSqlConnection* dbi_conn)
|
||||
/* ================================================================= */
|
||||
|
||||
static void
|
||||
create_tables_cb (const gchar* type, gpointer data_p, gpointer be_p)
|
||||
create_tables(const OBEEntry& entry, GncDbiBackend* be)
|
||||
{
|
||||
GncSqlObjectBackend* pData = static_cast<decltype (pData)> (data_p);
|
||||
GncDbiBackend* be = static_cast<decltype (be)> (be_p);
|
||||
std::string type;
|
||||
GncSqlObjectBackendPtr obe = nullptr;
|
||||
std::tie(type, obe) = entry;
|
||||
g_return_if_fail(obe->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
g_return_if_fail (type != NULL && data_p != NULL && be_p != NULL);
|
||||
g_return_if_fail (pData->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
if (pData->create_tables != NULL)
|
||||
if (obe->create_tables != nullptr)
|
||||
{
|
||||
(pData->create_tables) (&be->sql_be);
|
||||
(obe->create_tables)(&be->sql_be);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1627,7 +1626,9 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
|
||||
gnc_sql_init_version_info (&be->sql_be);
|
||||
|
||||
// Call all object backends to create any required tables
|
||||
qof_object_foreach_backend (GNC_SQL_BACKEND, create_tables_cb, be);
|
||||
auto registry = gnc_sql_get_backend_registry();
|
||||
for (auto entry : registry)
|
||||
create_tables(entry, be);
|
||||
}
|
||||
|
||||
gnc_sql_load (&be->sql_be, book, loadType);
|
||||
|
||||
@@ -35,9 +35,7 @@ extern "C"
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include <qof.h>
|
||||
#include <unittest-support.h>
|
||||
#include <test-stuff.h>
|
||||
/* For cleaning up the database */
|
||||
/* For cleaning up the database */
|
||||
#include <dbi/dbi.h>
|
||||
#include <gnc-uri-utils.h>
|
||||
/* For setup_business */
|
||||
@@ -53,9 +51,14 @@ extern "C"
|
||||
#include <gnc-prefs.h>
|
||||
}
|
||||
/* For test_conn_index_functions */
|
||||
#include "../gnc-backend-dbi-priv.h"
|
||||
extern "C"
|
||||
{
|
||||
#include <unittest-support.h>
|
||||
#include <test-stuff.h>
|
||||
}
|
||||
#include "test-dbi-stuff.h"
|
||||
#include "test-dbi-business-stuff.h"
|
||||
#include "../gnc-backend-dbi-priv.h"
|
||||
|
||||
#if LIBDBI_VERSION >= 900
|
||||
#define HAVE_LIBDBI_R 1
|
||||
|
||||
@@ -464,7 +464,7 @@ gnc_sql_init_account_handler (void)
|
||||
NULL /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (GNC_ID_ACCOUNT, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
|
||||
gnc_sql_register_col_type_handler (CT_ACCOUNTREF, &account_guid_handler);
|
||||
}
|
||||
|
||||
+136
-120
@@ -55,6 +55,9 @@ extern "C"
|
||||
#include "splint-defs.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "gnc-backend-sql.h"
|
||||
|
||||
#include "gnc-account-sql.h"
|
||||
@@ -125,9 +128,26 @@ 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_init (GncSqlBackend* be)
|
||||
gnc_sql_register_backend(GncSqlObjectBackendPtr obe)
|
||||
{
|
||||
backend_registry.emplace_back(make_tuple(std::string{obe->type_name}, obe));
|
||||
}
|
||||
|
||||
const OBEVec&
|
||||
gnc_sql_get_backend_registry()
|
||||
{
|
||||
return backend_registry;
|
||||
}
|
||||
void
|
||||
gnc_sql_init(GncSqlBackend* be)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
@@ -142,65 +162,54 @@ gnc_sql_init (GncSqlBackend* be)
|
||||
/* ================================================================= */
|
||||
|
||||
static void
|
||||
create_tables_cb (const gchar* type, gpointer data_p, gpointer be_p)
|
||||
create_tables(const OBEEntry& entry, GncSqlBackend* be)
|
||||
{
|
||||
GncSqlObjectBackend* pData = static_cast<decltype (pData)> (data_p);
|
||||
GncSqlBackend* be = static_cast<decltype (be)> (be_p);
|
||||
std::string type;
|
||||
GncSqlObjectBackendPtr obe = nullptr;
|
||||
std::tie(type, obe) = entry;
|
||||
g_return_if_fail (obe->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
g_return_if_fail (type != NULL && data_p != NULL && be_p != NULL);
|
||||
g_return_if_fail (pData->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
if (pData->create_tables != NULL)
|
||||
if (obe->create_tables != nullptr)
|
||||
{
|
||||
update_progress (be);
|
||||
(pData->create_tables) (be);
|
||||
update_progress(be);
|
||||
(obe->create_tables)(be);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================= */
|
||||
|
||||
/* Main object load order */
|
||||
static const gchar* fixed_load_order[] =
|
||||
{ GNC_ID_BOOK, GNC_ID_COMMODITY, GNC_ID_ACCOUNT, GNC_ID_LOT, NULL };
|
||||
static const LoadOrder fixed_load_order
|
||||
{ GNC_ID_BOOK, GNC_ID_COMMODITY, GNC_ID_ACCOUNT, GNC_ID_LOT };
|
||||
|
||||
|
||||
/* Load order for objects from other modules */
|
||||
static const gchar** other_load_order = NULL;
|
||||
static LoadOrder other_load_order;
|
||||
|
||||
void
|
||||
gnc_sql_set_load_order (const gchar** load_order)
|
||||
gnc_sql_set_load_order(const LoadOrder& load_order)
|
||||
{
|
||||
other_load_order = load_order;
|
||||
}
|
||||
|
||||
static void
|
||||
initial_load_cb (const gchar* type, gpointer data_p, gpointer be_p)
|
||||
initial_load(const OBEEntry& entry, GncSqlBackend* be)
|
||||
{
|
||||
GncSqlObjectBackend* pData = static_cast<decltype (pData)> (data_p);
|
||||
GncSqlBackend* be = static_cast<decltype (be)> (be_p);
|
||||
gint i;
|
||||
std::string type;
|
||||
GncSqlObjectBackendPtr obe = nullptr;
|
||||
std::tie(type, obe) = entry;
|
||||
g_return_if_fail(obe->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
g_return_if_fail (type != NULL && data_p != NULL && be_p != NULL);
|
||||
g_return_if_fail (pData->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(other_load_order.begin(), other_load_order.end(),
|
||||
type) != other_load_order.end()) return;
|
||||
|
||||
// Don't need to load anything if it has already been loaded with the fixed order
|
||||
for (i = 0; fixed_load_order[i] != NULL; i++)
|
||||
{
|
||||
update_progress (be);
|
||||
if (g_ascii_strcasecmp (type, fixed_load_order[i]) == 0) return;
|
||||
}
|
||||
if (other_load_order != NULL)
|
||||
{
|
||||
for (i = 0; other_load_order[i] != NULL; i++)
|
||||
{
|
||||
update_progress (be);
|
||||
if (g_ascii_strcasecmp (type, other_load_order[i]) == 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pData->initial_load != NULL)
|
||||
{
|
||||
(pData->initial_load) (be);
|
||||
}
|
||||
if (obe->initial_load != nullptr)
|
||||
(obe->initial_load)(be);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -220,8 +229,6 @@ commit_commodity (gpointer data)
|
||||
void
|
||||
gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
|
||||
{
|
||||
GncSqlObjectBackend* pData;
|
||||
gint i;
|
||||
Account* root;
|
||||
|
||||
g_return_if_fail (be != NULL);
|
||||
@@ -237,39 +244,46 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
|
||||
be->book = book;
|
||||
|
||||
/* Load any initial stuff. Some of this needs to happen in a certain order */
|
||||
for (i = 0; fixed_load_order[i] != NULL; i++)
|
||||
for (auto type : fixed_load_order)
|
||||
{
|
||||
pData = static_cast<decltype (pData)> (qof_object_lookup_backend (
|
||||
fixed_load_order[i],
|
||||
GNC_SQL_BACKEND));
|
||||
if (pData->initial_load != NULL)
|
||||
auto entry = std::find_if(backend_registry.begin(),
|
||||
backend_registry.end(),
|
||||
[type](const OBEEntry& entry){
|
||||
return type == std::get<0>(entry);
|
||||
});
|
||||
auto obe = std::get<1>(*entry);
|
||||
if (entry != backend_registry.end() &&
|
||||
obe->initial_load != nullptr)
|
||||
{
|
||||
update_progress (be);
|
||||
(pData->initial_load) (be);
|
||||
update_progress(be);
|
||||
(obe->initial_load)(be);
|
||||
}
|
||||
}
|
||||
if (other_load_order != NULL)
|
||||
for (auto type : other_load_order)
|
||||
{
|
||||
for (i = 0; other_load_order[i] != NULL; i++)
|
||||
auto entry = std::find_if(backend_registry.begin(),
|
||||
backend_registry.end(),
|
||||
[type](const OBEEntry& entry){
|
||||
return type == std::get<0>(entry);
|
||||
});
|
||||
auto obe = std::get<1>(*entry);
|
||||
if (entry != backend_registry.end() &&
|
||||
obe->initial_load != nullptr)
|
||||
{
|
||||
pData =
|
||||
static_cast<decltype (pData)> (qof_object_lookup_backend (
|
||||
other_load_order[i],
|
||||
GNC_SQL_BACKEND));
|
||||
if (pData->initial_load != NULL)
|
||||
{
|
||||
update_progress (be);
|
||||
(pData->initial_load) (be);
|
||||
}
|
||||
update_progress(be);
|
||||
(obe->initial_load)(be);
|
||||
}
|
||||
}
|
||||
|
||||
root = gnc_book_get_root_account (book);
|
||||
gnc_account_foreach_descendant (root, (AccountCb)xaccAccountBeginEdit, NULL);
|
||||
root = gnc_book_get_root_account( book );
|
||||
gnc_account_foreach_descendant(root, (AccountCb)xaccAccountBeginEdit,
|
||||
nullptr);
|
||||
|
||||
qof_object_foreach_backend (GNC_SQL_BACKEND, initial_load_cb, be);
|
||||
for (auto entry : backend_registry)
|
||||
initial_load(entry, be);
|
||||
|
||||
gnc_account_foreach_descendant (root, (AccountCb)xaccAccountCommitEdit, NULL);
|
||||
gnc_account_foreach_descendant(root, (AccountCb)xaccAccountCommitEdit,
|
||||
nullptr);
|
||||
}
|
||||
else if (loadType == LOAD_TYPE_LOAD_ALL)
|
||||
{
|
||||
@@ -414,18 +428,17 @@ write_schedXactions (GncSqlBackend* be)
|
||||
}
|
||||
|
||||
static void
|
||||
write_cb (const gchar* type, gpointer data_p, gpointer be_p)
|
||||
write(const OBEEntry& entry, GncSqlBackend* be)
|
||||
{
|
||||
GncSqlObjectBackend* pData = static_cast<decltype (pData)> (data_p);
|
||||
GncSqlBackend* be = static_cast<decltype (be)> (be_p);
|
||||
std::string type;
|
||||
GncSqlObjectBackendPtr obe = nullptr;
|
||||
std::tie(type, obe) = entry;
|
||||
g_return_if_fail (obe->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
g_return_if_fail (type != NULL && data_p != NULL && be_p != NULL);
|
||||
g_return_if_fail (pData->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
if (pData->write != NULL)
|
||||
if (obe->write != nullptr)
|
||||
{
|
||||
(void) (pData->write) (be);
|
||||
update_progress (be);
|
||||
(void)(obe->write)(be);
|
||||
update_progress(be);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +470,8 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
|
||||
|
||||
/* Create new tables */
|
||||
be->is_pristine_db = TRUE;
|
||||
qof_object_foreach_backend (GNC_SQL_BACKEND, create_tables_cb, be);
|
||||
for(auto entry : backend_registry)
|
||||
create_tables(entry, be);
|
||||
|
||||
/* Save all contents */
|
||||
be->book = book;
|
||||
@@ -493,7 +507,8 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
|
||||
}
|
||||
if (is_ok)
|
||||
{
|
||||
qof_object_foreach_backend (GNC_SQL_BACKEND, write_cb, be);
|
||||
for (auto entry : backend_registry)
|
||||
write(entry, be);
|
||||
}
|
||||
if (is_ok)
|
||||
{
|
||||
@@ -542,21 +557,22 @@ gnc_sql_rollback_edit (GncSqlBackend* be, QofInstance* inst)
|
||||
}
|
||||
|
||||
static void
|
||||
commit_cb (const gchar* type, gpointer data_p, gpointer be_data_p)
|
||||
commit(const OBEEntry& entry, sql_backend* be_data)
|
||||
{
|
||||
GncSqlObjectBackend* pData = static_cast<decltype (pData)> (data_p);
|
||||
sql_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
std::string type;
|
||||
GncSqlObjectBackendPtr obe= nullptr;
|
||||
std::tie(type, obe) = entry;
|
||||
g_return_if_fail (obe->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
g_return_if_fail (type != NULL && pData != NULL && be_data != NULL);
|
||||
g_return_if_fail (pData->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
/* If this has already been handled, or is not the correct handler, return */
|
||||
if (strcmp (pData->type_name, be_data->inst->e_type) != 0) return;
|
||||
/* 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;
|
||||
|
||||
if (pData->commit != NULL)
|
||||
if (obe->commit != nullptr)
|
||||
{
|
||||
be_data->is_ok = (pData->commit) (be_data->be, be_data->inst);
|
||||
be_data->is_ok = (obe->commit)(be_data->be, be_data->inst);
|
||||
be_data->is_known = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -625,7 +641,8 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
|
||||
be_data.inst = inst;
|
||||
be_data.is_ok = TRUE;
|
||||
|
||||
qof_object_foreach_backend (GNC_SQL_BACKEND, commit_cb, &be_data);
|
||||
for (auto entry : backend_registry)
|
||||
commit(entry, &be_data);
|
||||
|
||||
if (!be_data.is_known)
|
||||
{
|
||||
@@ -809,23 +826,22 @@ handle_and_term (QofQueryTerm* pTerm, GString* sql)
|
||||
}
|
||||
|
||||
static void
|
||||
compile_query_cb (const gchar* type, gpointer data_p, gpointer be_data_p)
|
||||
compile_query(const OBEEntry& entry, sql_backend* be_data)
|
||||
{
|
||||
GncSqlObjectBackend* pData = static_cast<decltype (pData)> (data_p);
|
||||
sql_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
|
||||
g_return_if_fail (type != NULL && pData != NULL && be_data != NULL);
|
||||
g_return_if_fail (pData->version == GNC_SQL_BACKEND_VERSION);
|
||||
std::string type;
|
||||
GncSqlObjectBackendPtr obe = nullptr;
|
||||
std::tie(type, obe) = entry;
|
||||
g_return_if_fail (obe->version == GNC_SQL_BACKEND_VERSION);
|
||||
|
||||
// Is this the right item?
|
||||
if (strcmp (type, be_data->pQueryInfo->searchObj) != 0) return;
|
||||
if (type != std::string{be_data->pQueryInfo->searchObj}) return;
|
||||
if (be_data->is_ok) return;
|
||||
|
||||
if (pData->compile_query != NULL)
|
||||
if (obe->compile_query != nullptr)
|
||||
{
|
||||
be_data->pQueryInfo->pCompiledQuery = (pData->compile_query) (
|
||||
be_data->be,
|
||||
be_data->pQuery);
|
||||
be_data->pQueryInfo->pCompiledQuery = (obe->compile_query)(
|
||||
be_data->be,
|
||||
be_data->pQuery);
|
||||
be_data->is_ok = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -860,7 +876,8 @@ gnc_sql_compile_query (QofBackend* pBEnd, QofQuery* pQuery)
|
||||
be_data.pQuery = pQuery;
|
||||
be_data.pQueryInfo = pQueryInfo;
|
||||
|
||||
qof_object_foreach_backend (GNC_SQL_BACKEND, compile_query_cb, &be_data);
|
||||
for (auto entry : backend_registry)
|
||||
compile_query(entry, &be_data);
|
||||
if (be_data.is_ok)
|
||||
{
|
||||
LEAVE ("");
|
||||
@@ -925,19 +942,18 @@ gnc_sql_compile_query_to_sql (GncSqlBackend* be, QofQuery* query)
|
||||
}
|
||||
|
||||
static void
|
||||
free_query_cb (const gchar* type, gpointer data_p, gpointer be_data_p)
|
||||
free_query(const OBEEntry& entry, sql_backend* be_data)
|
||||
{
|
||||
GncSqlObjectBackend* pData = static_cast<decltype (pData)> (data_p);
|
||||
sql_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
|
||||
g_return_if_fail (type != NULL && pData != NULL && be_data != NULL);
|
||||
g_return_if_fail (pData->version == GNC_SQL_BACKEND_VERSION);
|
||||
std::string type;
|
||||
GncSqlObjectBackendPtr obe= nullptr;
|
||||
std::tie(type, obe) = entry;
|
||||
g_return_if_fail (obe->version == GNC_SQL_BACKEND_VERSION);
|
||||
if (be_data->is_ok) return;
|
||||
if (strcmp (type, be_data->pQueryInfo->searchObj) != 0) return;
|
||||
if (type != std::string{be_data->pQueryInfo->searchObj}) return;
|
||||
|
||||
if (pData->free_query != NULL)
|
||||
if (obe->free_query != nullptr)
|
||||
{
|
||||
(pData->free_query) (be_data->be, be_data->pCompiledQuery);
|
||||
(obe->free_query)(be_data->be, be_data->pCompiledQuery);
|
||||
be_data->is_ok = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -960,7 +976,8 @@ gnc_sql_free_query (QofBackend* pBEnd, gpointer pQuery)
|
||||
be_data.pCompiledQuery = pQuery;
|
||||
be_data.pQueryInfo = pQueryInfo;
|
||||
|
||||
qof_object_foreach_backend (GNC_SQL_BACKEND, free_query_cb, &be_data);
|
||||
for (auto entry : backend_registry)
|
||||
free_query(entry, &be_data);
|
||||
if (be_data.is_ok)
|
||||
{
|
||||
LEAVE ("");
|
||||
@@ -978,21 +995,20 @@ gnc_sql_free_query (QofBackend* pBEnd, gpointer pQuery)
|
||||
}
|
||||
|
||||
static void
|
||||
run_query_cb (const gchar* type, gpointer data_p, gpointer be_data_p)
|
||||
run_query(const OBEEntry& entry, sql_backend* be_data)
|
||||
{
|
||||
GncSqlObjectBackend* pData = static_cast<decltype (pData)> (data_p);
|
||||
sql_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
|
||||
g_return_if_fail (type != NULL && pData != NULL && be_data != NULL);
|
||||
g_return_if_fail (pData->version == GNC_SQL_BACKEND_VERSION);
|
||||
std::string type;
|
||||
GncSqlObjectBackendPtr obe = nullptr;
|
||||
std::tie(type, obe) = entry;
|
||||
g_return_if_fail (obe->version == GNC_SQL_BACKEND_VERSION);
|
||||
if (be_data->is_ok) return;
|
||||
|
||||
// Is this the right item?
|
||||
if (strcmp (type, be_data->pQueryInfo->searchObj) != 0) return;
|
||||
if (type != std::string{be_data->pQueryInfo->searchObj}) return;
|
||||
|
||||
if (pData->run_query != NULL)
|
||||
if (obe->run_query != nullptr)
|
||||
{
|
||||
(pData->run_query) (be_data->be, be_data->pCompiledQuery);
|
||||
(obe->run_query)(be_data->be, be_data->pCompiledQuery);
|
||||
be_data->is_ok = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1020,8 +1036,8 @@ gnc_sql_run_query (QofBackend* pBEnd, gpointer pQuery)
|
||||
be_data.be = be;
|
||||
be_data.pCompiledQuery = pQueryInfo->pCompiledQuery;
|
||||
be_data.pQueryInfo = pQueryInfo;
|
||||
|
||||
qof_object_foreach_backend (GNC_SQL_BACKEND, run_query_cb, &be_data);
|
||||
for (auto entry : backend_registry)
|
||||
run_query(entry, &be_data);
|
||||
be->loading = FALSE;
|
||||
be->in_query = FALSE;
|
||||
qof_event_resume ();
|
||||
@@ -1040,8 +1056,8 @@ gnc_sql_run_query (QofBackend* pBEnd, gpointer pQuery)
|
||||
|
||||
/* ================================================================= */
|
||||
/* Order in which business objects need to be loaded */
|
||||
static const gchar* business_fixed_load_order[] =
|
||||
{ GNC_ID_BILLTERM, GNC_ID_TAXTABLE, GNC_ID_INVOICE, NULL };
|
||||
static const LoadOrder business_fixed_load_order =
|
||||
{ GNC_ID_BILLTERM, GNC_ID_TAXTABLE, GNC_ID_INVOICE };
|
||||
|
||||
static void
|
||||
business_core_sql_init (void)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/********************************************************************
|
||||
* gnc-backend-sql.h: load and save data to SQL *
|
||||
* *
|
||||
@@ -44,6 +45,13 @@ extern "C"
|
||||
#include "qofbackend-p.h"
|
||||
#include <gmodule.h>
|
||||
}
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using LoadOrder = std::vector<std::string>;
|
||||
typedef struct GncSqlConnection GncSqlConnection;
|
||||
|
||||
/**
|
||||
@@ -247,7 +255,7 @@ struct GncSqlResult
|
||||
* @struct GncSqlObjectBackend
|
||||
*
|
||||
* Struct used to handle a specific engine object type for an SQL backend.
|
||||
* This handler should be registered with qof_object_register_backend().
|
||||
* This handler should be registered with gnc_sql_register_backend().
|
||||
*
|
||||
* commit() - commit an object to the db
|
||||
* initial_load() - load stuff when new db opened
|
||||
@@ -259,8 +267,8 @@ struct GncSqlResult
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int version; /**< Backend version number */
|
||||
const gchar* type_name; /**< Engine object type name */
|
||||
int version; /**< Backend version number */
|
||||
const std::string type_name; /**< Engine object type name */
|
||||
/** Commit an instance of this object to the database
|
||||
* @return TRUE if successful, FALSE if error
|
||||
*/
|
||||
@@ -281,7 +289,13 @@ typedef struct
|
||||
gboolean (*write) (GncSqlBackend* be);
|
||||
} GncSqlObjectBackend;
|
||||
#define GNC_SQL_BACKEND "gnc:sql:1"
|
||||
#define GNC_SQL_BACKEND_VERSION 1
|
||||
#define GNC_SQL_BACKEND_VERSION 1
|
||||
using GncSqlObjectBackendPtr = GncSqlObjectBackend*;
|
||||
using OBEEntry = std::tuple<std::string, GncSqlObjectBackendPtr>;
|
||||
using OBEVec = std::vector<OBEEntry>;
|
||||
void gnc_sql_register_backend(OBEEntry&&);
|
||||
void gnc_sql_register_backend(GncSqlObjectBackendPtr);
|
||||
const OBEVec& gnc_sql_get_backend_registry();
|
||||
|
||||
/**
|
||||
* Basic column type
|
||||
@@ -762,7 +776,7 @@ gboolean gnc_sql_add_columns_to_table (GncSqlBackend* be,
|
||||
*
|
||||
* @param load_order NULL-terminated array of object type ID strings
|
||||
*/
|
||||
void gnc_sql_set_load_order (const gchar** load_order);
|
||||
void gnc_sql_set_load_order(LoadOrder&& load_order);
|
||||
|
||||
void _retrieve_guid_ (gpointer pObject, gpointer pValue);
|
||||
|
||||
|
||||
@@ -411,8 +411,7 @@ gnc_billterm_sql_initialize (void)
|
||||
write_billterms /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_BILLTERM, GNC_SQL_BACKEND, &be_data);
|
||||
|
||||
gnc_sql_register_backend(&be_data);
|
||||
gnc_sql_register_col_type_handler (CT_BILLTERMREF, &billterm_guid_handler);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -245,6 +245,6 @@ gnc_sql_init_book_handler (void)
|
||||
NULL /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (GNC_ID_BOOK, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -545,8 +545,7 @@ gnc_sql_init_budget_handler (void)
|
||||
write_budgets /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (GNC_ID_BUDGET, GNC_SQL_BACKEND, &be_data);
|
||||
|
||||
gnc_sql_register_backend(&be_data);
|
||||
gnc_sql_register_col_type_handler (CT_BUDGETREF, &budget_guid_handler);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -336,9 +336,7 @@ gnc_sql_init_commodity_handler (void)
|
||||
NULL /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (GNC_ID_COMMODITY, GNC_SQL_BACKEND,
|
||||
&be_data);
|
||||
|
||||
gnc_sql_register_backend(&be_data);
|
||||
gnc_sql_register_col_type_handler (CT_COMMODITYREF, &commodity_guid_handler);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -248,6 +248,6 @@ gnc_customer_sql_initialize (void)
|
||||
write_customers /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_CUSTOMER, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -275,6 +275,6 @@ gnc_employee_sql_initialize (void)
|
||||
write_employees /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_EMPLOYEE, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -295,6 +295,6 @@ gnc_entry_sql_initialize (void)
|
||||
write_entries /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_ENTRY, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -345,8 +345,7 @@ gnc_invoice_sql_initialize (void)
|
||||
write_invoices /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_INVOICE, GNC_SQL_BACKEND, &be_data);
|
||||
|
||||
gnc_sql_register_backend(&be_data);
|
||||
gnc_sql_register_col_type_handler (CT_INVOICEREF, &invoice_guid_handler);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -217,6 +217,6 @@ gnc_job_sql_initialize (void)
|
||||
write_jobs /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_JOB, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -276,8 +276,7 @@ gnc_sql_init_lot_handler (void)
|
||||
write_lots /* save all */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (GNC_ID_LOT, GNC_SQL_BACKEND, &be_data);
|
||||
|
||||
gnc_sql_register_backend(&be_data);
|
||||
gnc_sql_register_col_type_handler (CT_LOTREF, &lot_guid_handler);
|
||||
}
|
||||
|
||||
|
||||
@@ -260,8 +260,7 @@ gnc_order_sql_initialize (void)
|
||||
write_orders /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_ORDER, GNC_SQL_BACKEND, &be_data);
|
||||
|
||||
gnc_sql_register_backend(&be_data);
|
||||
gnc_sql_register_col_type_handler (CT_ORDERREF, &order_guid_handler);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -242,7 +242,7 @@ gnc_sql_init_price_handler (void)
|
||||
write_prices /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (GNC_ID_PRICE, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -459,6 +459,6 @@ gnc_sql_init_recurrence_handler (void)
|
||||
NULL /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (TABLE_NAME, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -233,7 +233,6 @@ gnc_sql_init_schedxaction_handler (void)
|
||||
NULL /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (GNC_ID_SCHEDXACTION, GNC_SQL_BACKEND,
|
||||
&be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -1100,6 +1100,10 @@ gnc_sql_init_slots_handler (void)
|
||||
static GncSqlObjectBackend be_data =
|
||||
{
|
||||
GNC_SQL_BACKEND_VERSION,
|
||||
// This was GNC_ID_ACCOUNT. If somethine blows up, change it back,
|
||||
// make the registry store a std::tuple<std::string,
|
||||
// GncSqlObjectBackendPtr>, and check the first string against types
|
||||
// in the functions that are called on each backend.
|
||||
GNC_ID_ACCOUNT,
|
||||
NULL, /* commit - cannot occur */
|
||||
NULL, /* initial_load - cannot occur */
|
||||
@@ -1110,6 +1114,7 @@ gnc_sql_init_slots_handler (void)
|
||||
NULL /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (TABLE_NAME, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(std::make_tuple(std::string{TABLE_NAME},
|
||||
&be_data));
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -569,8 +569,7 @@ gnc_taxtable_sql_initialize (void)
|
||||
write_taxtables /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_TAXTABLE, GNC_SQL_BACKEND, &be_data);
|
||||
|
||||
gnc_sql_register_backend(&be_data);
|
||||
gnc_sql_register_col_type_handler (CT_TAXTABLEREF, &taxtable_guid_handler);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -1540,10 +1540,8 @@ gnc_sql_init_transaction_handler (void)
|
||||
NULL /* write */
|
||||
};
|
||||
|
||||
(void)qof_object_register_backend (GNC_ID_TRANS, GNC_SQL_BACKEND, &be_data_tx);
|
||||
(void)qof_object_register_backend (GNC_ID_SPLIT, GNC_SQL_BACKEND,
|
||||
&be_data_split);
|
||||
|
||||
gnc_sql_register_backend(&be_data_tx);
|
||||
gnc_sql_register_backend(&be_data_split);
|
||||
gnc_sql_register_col_type_handler (CT_TXREF, &tx_guid_handler);
|
||||
}
|
||||
|
||||
|
||||
@@ -268,6 +268,6 @@ gnc_vendor_sql_initialize (void)
|
||||
write_vendors /* write */
|
||||
};
|
||||
|
||||
qof_object_register_backend (GNC_ID_VENDOR, GNC_SQL_BACKEND, &be_data);
|
||||
gnc_sql_register_backend(&be_data);
|
||||
}
|
||||
/* ========================== END OF FILE ===================== */
|
||||
|
||||
@@ -27,10 +27,13 @@ extern "C"
|
||||
{
|
||||
#include "config.h"
|
||||
#include "qof.h"
|
||||
}
|
||||
#include "gnc-backend-sql.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "cashobjects.h"
|
||||
#include "test-stuff.h"
|
||||
}
|
||||
#include "gnc-backend-sql.h"
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
|
||||
@@ -238,7 +238,5 @@ gnc_address_xml_initialize (void)
|
||||
address_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend ("gnc:Address",
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend (be_data);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ extern "C"
|
||||
#include "gnc-engine.h"
|
||||
|
||||
#include "gnc-uri-utils.h"
|
||||
#include "io-gncxml-v2.h"
|
||||
#include "gnc-prefs.h"
|
||||
|
||||
#ifndef HAVE_STRPTIME
|
||||
@@ -89,6 +88,7 @@ extern "C"
|
||||
#include "gnc-backend-xml.h"
|
||||
#include <qofbackend-p.h>
|
||||
#include "gnc-xml-helper.h"
|
||||
#include "io-gncxml-v2.h"
|
||||
#include "io-gncxml.h"
|
||||
|
||||
#include "gnc-address-xml-v2.h"
|
||||
|
||||
@@ -774,9 +774,7 @@ gnc_billterm_xml_initialize (void)
|
||||
billterm_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend(be_data);
|
||||
}
|
||||
|
||||
GncBillTerm*
|
||||
|
||||
@@ -538,7 +538,5 @@ gnc_customer_xml_initialize (void)
|
||||
customer_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend (be_data);
|
||||
}
|
||||
|
||||
@@ -460,7 +460,5 @@ gnc_employee_xml_initialize (void)
|
||||
employee_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend (be_data);
|
||||
}
|
||||
|
||||
@@ -863,7 +863,5 @@ gnc_entry_xml_initialize (void)
|
||||
entry_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend (be_data);
|
||||
}
|
||||
|
||||
@@ -571,7 +571,5 @@ gnc_invoice_xml_initialize (void)
|
||||
invoice_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend(be_data);
|
||||
}
|
||||
|
||||
@@ -359,7 +359,5 @@ gnc_job_xml_initialize (void)
|
||||
job_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend(be_data);
|
||||
}
|
||||
|
||||
@@ -401,7 +401,5 @@ gnc_order_xml_initialize (void)
|
||||
order_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend(be_data);
|
||||
}
|
||||
|
||||
@@ -239,7 +239,5 @@ gnc_owner_xml_initialize (void)
|
||||
owner_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend ("gnc:Owner",
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend (be_data);
|
||||
}
|
||||
|
||||
@@ -719,7 +719,5 @@ gnc_taxtable_xml_initialize (void)
|
||||
taxtable_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend(be_data);
|
||||
}
|
||||
|
||||
@@ -480,7 +480,5 @@ gnc_vendor_xml_initialize (void)
|
||||
vendor_ns,
|
||||
};
|
||||
|
||||
qof_object_register_backend (_GNC_MOD_NAME,
|
||||
GNC_FILE_BACKEND,
|
||||
&be_data);
|
||||
gnc_xml_register_backend(be_data);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ extern "C"
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "sixtp.h"
|
||||
#include "sixtp-parsers.h"
|
||||
#include "sixtp-utils.h"
|
||||
#include "gnc-xml.h"
|
||||
@@ -109,6 +108,13 @@ struct file_backend
|
||||
QofBook* book;
|
||||
};
|
||||
|
||||
static std::vector<GncXmlDataType_t> backend_registry;
|
||||
void
|
||||
gnc_xml_register_backend(GncXmlDataType_t& xmlbe)
|
||||
{
|
||||
backend_registry.push_back(xmlbe);
|
||||
}
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
/* non-static because they are used in sixtp.c */
|
||||
const gchar* gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
@@ -356,18 +362,14 @@ add_pricedb_local (sixtp_gdv2* data, GNCPriceDB* db)
|
||||
}
|
||||
|
||||
static void
|
||||
do_counter_cb (const char* type, gpointer data_p, gpointer be_data_p)
|
||||
counter (const GncXmlDataType_t& data, file_backend* be_data)
|
||||
{
|
||||
GncXmlDataType_t* data = static_cast<decltype (data)> (data_p);
|
||||
struct file_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
|
||||
g_return_if_fail (type && data && be_data);
|
||||
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
|
||||
g_return_if_fail (data.version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
if (be_data->ok == TRUE)
|
||||
return;
|
||||
|
||||
if (!g_strcmp0 (be_data->tag, data->type_name))
|
||||
if (!g_strcmp0 (be_data->tag, data.type_name))
|
||||
be_data->ok = TRUE;
|
||||
|
||||
/* XXX: should we do anything with this counter? */
|
||||
@@ -443,8 +445,8 @@ gnc_counter_end_handler (gpointer data_for_children,
|
||||
|
||||
be_data.ok = FALSE;
|
||||
be_data.tag = type;
|
||||
|
||||
qof_object_foreach_backend (GNC_FILE_BACKEND, do_counter_cb, &be_data);
|
||||
for(auto data : backend_registry)
|
||||
counter(data, &be_data);
|
||||
|
||||
if (be_data.ok == FALSE)
|
||||
{
|
||||
@@ -544,21 +546,17 @@ static const char* TEMPLATE_TRANSACTION_TAG = "gnc:template-transactions";
|
||||
static const char* BUDGET_TAG = "gnc:budget";
|
||||
|
||||
static void
|
||||
add_item_cb (const char* type, gpointer data_p, gpointer be_data_p)
|
||||
add_item (const GncXmlDataType_t& data, struct file_backend* be_data)
|
||||
{
|
||||
GncXmlDataType_t* data = static_cast<decltype (data)> (data_p);
|
||||
struct file_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
|
||||
g_return_if_fail (type && data && be_data);
|
||||
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
|
||||
g_return_if_fail (data.version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
if (be_data->ok)
|
||||
return;
|
||||
|
||||
if (!g_strcmp0 (be_data->tag, data->type_name))
|
||||
if (!g_strcmp0 (be_data->tag, data.type_name))
|
||||
{
|
||||
if (data->add_item)
|
||||
(data->add_item) (be_data->gd, be_data->data);
|
||||
if (data.add_item)
|
||||
(data.add_item)(be_data->gd, be_data->data);
|
||||
|
||||
be_data->ok = TRUE;
|
||||
}
|
||||
@@ -606,7 +604,8 @@ book_callback (const char* tag, gpointer globaldata, gpointer data)
|
||||
be_data.gd = gd;
|
||||
be_data.data = data;
|
||||
|
||||
qof_object_foreach_backend (GNC_FILE_BACKEND, add_item_cb, &be_data);
|
||||
for (auto data : backend_registry)
|
||||
add_item(data, &be_data);
|
||||
|
||||
if (be_data.ok == FALSE)
|
||||
{
|
||||
@@ -635,36 +634,28 @@ generic_callback (const char* tag, gpointer globaldata, gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
add_parser_cb (const char* type, gpointer data_p, gpointer be_data_p)
|
||||
add_parser(const GncXmlDataType_t& data, struct file_backend* be_data)
|
||||
{
|
||||
GncXmlDataType_t* data = static_cast<decltype (data)> (data_p);
|
||||
struct file_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
|
||||
g_return_if_fail (type && data && be_data);
|
||||
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
|
||||
g_return_if_fail (data.version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
if (be_data->ok == FALSE)
|
||||
return;
|
||||
|
||||
if (data->create_parser)
|
||||
if (!sixtp_add_some_sub_parsers (
|
||||
be_data->parser, TRUE,
|
||||
data->type_name, (data->create_parser) (),
|
||||
NULL, NULL))
|
||||
if (data.create_parser)
|
||||
if (!sixtp_add_some_sub_parsers(
|
||||
be_data->parser, TRUE,
|
||||
data.type_name, (data.create_parser)(),
|
||||
NULL, NULL))
|
||||
be_data->ok = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
scrub_cb (const char* type, gpointer data_p, gpointer be_data_p)
|
||||
scrub (const GncXmlDataType_t& data, struct file_backend* be_data)
|
||||
{
|
||||
GncXmlDataType_t* data = static_cast<decltype (data)> (data_p);
|
||||
struct file_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
g_return_if_fail (data.version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
g_return_if_fail (type && data && be_data);
|
||||
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
if (data->scrub)
|
||||
(data->scrub) (be_data->book);
|
||||
if (data.scrub)
|
||||
(data.scrub)(be_data->book);
|
||||
}
|
||||
|
||||
static sixtp_gdv2*
|
||||
@@ -773,7 +764,8 @@ qof_session_load_from_xml_file_v2_full (
|
||||
|
||||
be_data.ok = TRUE;
|
||||
be_data.parser = book_parser;
|
||||
qof_object_foreach_backend (GNC_FILE_BACKEND, add_parser_cb, &be_data);
|
||||
for (auto data : backend_registry)
|
||||
add_parser(data, &be_data);
|
||||
if (be_data.ok == FALSE)
|
||||
goto bail;
|
||||
|
||||
@@ -841,7 +833,8 @@ qof_session_load_from_xml_file_v2_full (
|
||||
/* Call individual scrub functions */
|
||||
memset (&be_data, 0, sizeof (be_data));
|
||||
be_data.book = book;
|
||||
qof_object_foreach_backend (GNC_FILE_BACKEND, scrub_cb, &be_data);
|
||||
for (auto data : backend_registry)
|
||||
scrub(data, &be_data);
|
||||
|
||||
/* fix price quote sources */
|
||||
root = gnc_book_get_root_account (book);
|
||||
@@ -963,31 +956,23 @@ static gboolean write_schedXactions (FILE* out, QofBook* book, sixtp_gdv2* gd);
|
||||
static void write_budget (QofInstance* ent, gpointer data);
|
||||
|
||||
static void
|
||||
write_counts_cb (const char* type, gpointer data_p, gpointer be_data_p)
|
||||
write_counts(const GncXmlDataType_t& data, struct file_backend* be_data)
|
||||
{
|
||||
GncXmlDataType_t* data = static_cast<decltype (data)> (data_p);
|
||||
struct file_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
g_return_if_fail (data.version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
g_return_if_fail (type && data && be_data);
|
||||
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
if (data->get_count)
|
||||
write_counts (be_data->out, data->type_name,
|
||||
(data->get_count) (be_data->book),
|
||||
if (data.get_count)
|
||||
write_counts (be_data->out, data.type_name,
|
||||
(data.get_count) (be_data->book),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
write_data_cb (const char* type, gpointer data_p, gpointer be_data_p)
|
||||
write_data(const GncXmlDataType_t& data, struct file_backend* be_data)
|
||||
{
|
||||
GncXmlDataType_t* data = static_cast<decltype (data)> (data_p);
|
||||
struct file_backend* be_data = static_cast<decltype (be_data)> (be_data_p);
|
||||
g_return_if_fail (data.version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
g_return_if_fail (type && data && be_data);
|
||||
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
if (data->write && !ferror (be_data->out))
|
||||
(data->write) (be_data->out, be_data->book);
|
||||
if (data.write && !ferror(be_data->out))
|
||||
(data.write)(be_data->out, be_data->book);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1048,7 +1033,8 @@ write_book (FILE* out, QofBook* book, sixtp_gdv2* gd)
|
||||
NULL))
|
||||
return FALSE;
|
||||
|
||||
qof_object_foreach_backend (GNC_FILE_BACKEND, write_counts_cb, &be_data);
|
||||
for (auto data : backend_registry)
|
||||
write_counts(data, &be_data);
|
||||
|
||||
if (ferror (out)
|
||||
|| !write_commodities (out, book, gd)
|
||||
@@ -1065,8 +1051,9 @@ write_book (FILE* out, QofBook* book, sixtp_gdv2* gd)
|
||||
if (ferror (out))
|
||||
return FALSE;
|
||||
|
||||
qof_object_foreach_backend (GNC_FILE_BACKEND, write_data_cb, &be_data);
|
||||
if (ferror (out))
|
||||
for (auto data : backend_registry)
|
||||
write_data(data, &be_data);
|
||||
if (ferror(out))
|
||||
return FALSE;
|
||||
|
||||
if (fprintf (out, "</%s>\n", BOOK_TAG) < 0)
|
||||
@@ -1296,16 +1283,12 @@ gnc_xml2_write_namespace_decl (FILE* out, const char* name_space)
|
||||
}
|
||||
|
||||
static void
|
||||
do_write_namespace_cb (const char* type, gpointer data_p, gpointer file_p)
|
||||
write_namespace (const GncXmlDataType_t& data, FILE* out)
|
||||
{
|
||||
GncXmlDataType_t* data = static_cast<decltype (data)> (data_p);
|
||||
FILE* out = static_cast<decltype (out)> (file_p);
|
||||
g_return_if_fail (data.version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
g_return_if_fail (type && data && out);
|
||||
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
|
||||
|
||||
if (data->ns && !ferror (out))
|
||||
(data->ns) (out);
|
||||
if (data.ns && !ferror(out))
|
||||
(data.ns)(out);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1333,7 +1316,8 @@ write_v2_header (FILE* out)
|
||||
return FALSE;
|
||||
|
||||
/* now cope with the plugins */
|
||||
qof_object_foreach_backend (GNC_FILE_BACKEND, do_write_namespace_cb, out);
|
||||
for (auto data : backend_registry)
|
||||
write_namespace(data, out);
|
||||
|
||||
if (ferror (out) || fprintf (out, ">\n") < 0)
|
||||
return FALSE;
|
||||
|
||||
@@ -37,8 +37,11 @@ extern "C"
|
||||
#include <glib.h>
|
||||
|
||||
#include "gnc-engine.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#include "gnc-backend-xml.h"
|
||||
|
||||
#include "sixtp.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
/**
|
||||
@@ -106,6 +109,13 @@ QofBookFileType gnc_is_xml_data_file_v2 (const gchar* name,
|
||||
*/
|
||||
gboolean gnc_xml2_write_namespace_decl (FILE* out, const char* name_space);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus. The next two functions are used (only) by
|
||||
* src/gnome-utils/assistant-xml-encoding.c and so need C linkage;
|
||||
* they're also the only part of this file that the C compiler needs to
|
||||
* see.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -147,5 +157,19 @@ gboolean gnc_xml2_parse_with_subst (
|
||||
FileBackend* fbe, QofBook* book, GHashTable* subst);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
int version; /* backend version number */
|
||||
const char * type_name; /* The XML tag for this type */
|
||||
|
||||
sixtp * (*create_parser) (void);
|
||||
gboolean (*add_item)(sixtp_gdv2 *, gpointer obj);
|
||||
int (*get_count) (QofBook *);
|
||||
gboolean (*write) (FILE*, QofBook*);
|
||||
void (*scrub) (QofBook *);
|
||||
gboolean (*ns) (FILE*);
|
||||
} GncXmlDataType_t;
|
||||
|
||||
void gnc_xml_register_backend(GncXmlDataType_t&);
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __IO_GNCXML_V2_H__ */
|
||||
|
||||
@@ -199,21 +199,6 @@ typedef struct sixtp_sax_data
|
||||
sixtp* bad_xml_parser;
|
||||
} sixtp_sax_data;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int version; /* backend version number */
|
||||
const char* type_name; /* The XML tag for this type */
|
||||
|
||||
sixtp* (*create_parser) (void);
|
||||
gboolean (*add_item) (sixtp_gdv2*, gpointer obj);
|
||||
int (*get_count) (QofBook*);
|
||||
gboolean (*write) (FILE*, QofBook*);
|
||||
void (*scrub) (QofBook*);
|
||||
gboolean (*ns) (FILE*);
|
||||
} GncXmlDataType_t;
|
||||
|
||||
|
||||
|
||||
gboolean is_child_result_from_node_named (sixtp_child_result* cr,
|
||||
const char* tag);
|
||||
void sixtp_child_free_data (sixtp_child_result* result);
|
||||
|
||||
@@ -37,7 +37,6 @@ static QofLogModule log_module = QOF_MOD_OBJECT;
|
||||
static gboolean object_is_initialized = FALSE;
|
||||
static GList *object_modules = NULL;
|
||||
static GList *book_list = NULL;
|
||||
static GHashTable *backend_data = NULL;
|
||||
|
||||
/*
|
||||
* These getters are used in tests to reach static vars from outside
|
||||
@@ -52,7 +51,6 @@ extern "C"
|
||||
gboolean get_object_is_initialized( void );
|
||||
GList* get_object_modules( void );
|
||||
GList* get_book_list( void );
|
||||
GHashTable* get_backend_data( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@@ -76,12 +74,6 @@ get_book_list( void )
|
||||
return book_list;
|
||||
}
|
||||
|
||||
GHashTable*
|
||||
get_backend_data( void )
|
||||
{
|
||||
return backend_data;
|
||||
}
|
||||
|
||||
/*********/
|
||||
|
||||
gpointer
|
||||
@@ -306,7 +298,6 @@ static gboolean clear_table (gpointer key, gpointer value, gpointer user_data)
|
||||
void qof_object_initialize (void)
|
||||
{
|
||||
if (object_is_initialized) return;
|
||||
backend_data = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
object_is_initialized = TRUE;
|
||||
}
|
||||
|
||||
@@ -314,10 +305,6 @@ void qof_object_shutdown (void)
|
||||
{
|
||||
g_return_if_fail (object_is_initialized == TRUE);
|
||||
|
||||
g_hash_table_foreach_remove (backend_data, clear_table, NULL);
|
||||
g_hash_table_destroy (backend_data);
|
||||
backend_data = NULL;
|
||||
|
||||
g_list_free (object_modules);
|
||||
object_modules = NULL;
|
||||
g_list_free (book_list);
|
||||
@@ -371,84 +358,4 @@ const QofObject * qof_object_lookup (QofIdTypeConst name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean qof_object_register_backend (QofIdTypeConst type_name,
|
||||
const char *backend_name,
|
||||
gpointer be_data)
|
||||
{
|
||||
GHashTable *ht;
|
||||
g_return_val_if_fail (object_is_initialized, FALSE);
|
||||
|
||||
if (!type_name || *type_name == '\0' ||
|
||||
!backend_name || *backend_name == '\0' ||
|
||||
!be_data)
|
||||
return FALSE;
|
||||
|
||||
ht = static_cast<GHashTable*>(g_hash_table_lookup (backend_data, backend_name));
|
||||
|
||||
/* If it doesn't already exist, create a new table for this backend */
|
||||
if (!ht)
|
||||
{
|
||||
ht = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
g_hash_table_insert (backend_data, (char *)backend_name, ht);
|
||||
}
|
||||
|
||||
/* Now insert the data */
|
||||
g_hash_table_insert (ht, (char *)type_name, be_data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
|
||||
const char *backend_name)
|
||||
{
|
||||
GHashTable *ht;
|
||||
|
||||
if (!type_name || *type_name == '\0' ||
|
||||
!backend_name || *backend_name == '\0')
|
||||
return NULL;
|
||||
|
||||
ht = static_cast<GHashTable*>(g_hash_table_lookup (backend_data, (char *)backend_name));
|
||||
if (!ht)
|
||||
return NULL;
|
||||
|
||||
return g_hash_table_lookup (ht, (char *)type_name);
|
||||
}
|
||||
|
||||
struct foreach_data
|
||||
{
|
||||
QofForeachBackendTypeCB cb;
|
||||
gpointer user_data;
|
||||
};
|
||||
|
||||
static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
|
||||
{
|
||||
char *data_type = static_cast<char*>(key);
|
||||
struct foreach_data *cb_data = static_cast<struct foreach_data*>(arg);
|
||||
|
||||
g_return_if_fail (key && be_item && arg);
|
||||
|
||||
/* Call the callback for this data type */
|
||||
(cb_data->cb) (data_type, be_item, cb_data->user_data);
|
||||
}
|
||||
|
||||
void qof_object_foreach_backend (const char *backend_name,
|
||||
QofForeachBackendTypeCB cb,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashTable *ht;
|
||||
struct foreach_data cb_data;
|
||||
|
||||
if (!backend_name || *backend_name == '\0' || !cb)
|
||||
return;
|
||||
|
||||
ht = static_cast<GHashTable*>(g_hash_table_lookup (backend_data, (char *)backend_name));
|
||||
if (!ht)
|
||||
return;
|
||||
|
||||
cb_data.cb = cb;
|
||||
cb_data.user_data = user_data;
|
||||
|
||||
g_hash_table_foreach_sorted (ht, foreach_backend, &cb_data, (GCompareFunc)strcmp);
|
||||
}
|
||||
|
||||
/* ========================= END OF FILE =================== */
|
||||
|
||||
@@ -171,19 +171,6 @@ void qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
|
||||
void qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book,
|
||||
QofInstanceForeachCB cb, gpointer user_data);
|
||||
|
||||
/** Register and lookup backend-specific data for this particular object */
|
||||
gboolean qof_object_register_backend (QofIdTypeConst type_name,
|
||||
const char *backend_name,
|
||||
gpointer be_data);
|
||||
|
||||
/*@ dependent @*/
|
||||
gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
|
||||
const char *backend_name);
|
||||
|
||||
void qof_object_foreach_backend (const char *backend_name,
|
||||
QofForeachBackendTypeCB cb,
|
||||
gpointer user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -93,7 +93,6 @@ extern "C"
|
||||
extern gboolean get_object_is_initialized( void );
|
||||
extern GList* get_object_modules( void );
|
||||
extern GList* get_book_list( void );
|
||||
extern GHashTable* get_backend_data( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@@ -229,36 +228,6 @@ test_qof_object_lookup( Fixture *fixture, gconstpointer pData )
|
||||
g_assert( qof_object_lookup( "anytype" ) == NULL );
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
gpointer data1;
|
||||
gpointer data2;
|
||||
} be_data;
|
||||
|
||||
static void
|
||||
test_qof_object_backend_register_lookup( Fixture *fixture, gconstpointer pData )
|
||||
{
|
||||
g_test_message( "Test register and lookup null checks" );
|
||||
g_assert( qof_object_register_backend( NULL, "test", &be_data ) == FALSE );
|
||||
g_assert( qof_object_register_backend( "", "test", &be_data ) == FALSE );
|
||||
g_assert( qof_object_register_backend( "test", NULL, &be_data ) == FALSE );
|
||||
g_assert( qof_object_register_backend( "test", "", &be_data ) == FALSE );
|
||||
g_assert( qof_object_register_backend( "test", "test", NULL ) == FALSE );
|
||||
g_assert( qof_object_lookup_backend( NULL, "test" ) == NULL );
|
||||
g_assert( qof_object_lookup_backend( "", "test" ) == NULL );
|
||||
g_assert( qof_object_lookup_backend( "test", NULL ) == NULL );
|
||||
g_assert( qof_object_lookup_backend( "test", "" ) == NULL );
|
||||
|
||||
g_test_message( "Test new backend and type insert" );
|
||||
g_assert( qof_object_lookup_backend( "type", "backend" ) == NULL );
|
||||
g_assert( qof_object_register_backend( "type", "backend", &be_data.data1 ) == TRUE );
|
||||
g_assert( qof_object_lookup_backend( "type", "backend" ) == &be_data.data1 );
|
||||
|
||||
g_test_message( "Test type insert into existing backend" );
|
||||
g_assert( qof_object_register_backend( "type2", "backend", &be_data.data2 ) == TRUE );
|
||||
g_assert( qof_object_lookup_backend( "type", "backend" ) == &be_data.data1 );
|
||||
g_assert( qof_object_lookup_backend( "type2", "backend" ) == &be_data.data2 );
|
||||
}
|
||||
|
||||
static void
|
||||
test_qof_object_get_type_label( Fixture *fixture, gconstpointer pData )
|
||||
@@ -732,50 +701,11 @@ test_qof_object_foreach_sorted( Fixture *fixture, gconstpointer pData )
|
||||
g_list_free( foreach_for_sorted_struct.instances );
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
QofIdTypeConst type;
|
||||
gpointer backend_data;
|
||||
gpointer user_data;
|
||||
guint call_count;
|
||||
} foreach_backend_struct;
|
||||
|
||||
static void
|
||||
mock_foreach_backend( QofIdTypeConst type, gpointer backend_data, gpointer user_data)
|
||||
{
|
||||
g_assert( type );
|
||||
g_assert( backend_data );
|
||||
g_assert( user_data );
|
||||
g_assert_cmpstr( type, == , foreach_backend_struct.type );
|
||||
g_assert( backend_data == foreach_backend_struct.backend_data );
|
||||
g_assert( user_data == foreach_backend_struct.user_data );
|
||||
foreach_backend_struct.call_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
test_qof_object_foreach_backend( Fixture *fixture, gconstpointer pData )
|
||||
{
|
||||
gint backend_data;
|
||||
gint user_data;
|
||||
|
||||
g_assert_cmpint( g_hash_table_size( get_backend_data() ), == , 0 );
|
||||
qof_object_register_backend( "type1", "backend", (gpointer) &backend_data ); /* register backend */
|
||||
g_assert_cmpint( g_hash_table_size( get_backend_data() ), == , 1 );
|
||||
|
||||
foreach_backend_struct.call_count = 0;
|
||||
foreach_backend_struct.backend_data = (gpointer) &backend_data;
|
||||
foreach_backend_struct.user_data = (gpointer) &user_data;
|
||||
foreach_backend_struct.type = "type1";
|
||||
qof_object_foreach_backend ( "backend", mock_foreach_backend, (gpointer) &user_data);
|
||||
g_assert_cmpint( foreach_backend_struct.call_count, == , 1 );
|
||||
}
|
||||
|
||||
void
|
||||
test_suite_qofobject (void)
|
||||
{
|
||||
GNC_TEST_ADD( suitename, "qof object register", Fixture, NULL, setup, test_qof_object_register, teardown );
|
||||
GNC_TEST_ADD( suitename, "qof object lookup", Fixture, NULL, setup, test_qof_object_lookup, teardown );
|
||||
GNC_TEST_ADD( suitename, "qof object register and lookup backend", Fixture, NULL, setup, test_qof_object_backend_register_lookup, teardown );
|
||||
GNC_TEST_ADD( suitename, "qof object get type label", Fixture, NULL, setup, test_qof_object_get_type_label, teardown );
|
||||
GNC_TEST_ADD( suitename, "qof object printable", Fixture, NULL, setup, test_qof_object_printable, teardown );
|
||||
GNC_TEST_ADD( suitename, "qof object book begin", Fixture, NULL, setup, test_qof_object_book_begin, teardown );
|
||||
@@ -787,5 +717,4 @@ test_suite_qofobject (void)
|
||||
GNC_TEST_ADD( suitename, "qof object foreach type", Fixture, NULL, setup, test_qof_object_foreach_type, teardown );
|
||||
GNC_TEST_ADD( suitename, "qof object foreach", Fixture, NULL, setup, test_qof_object_foreach, teardown );
|
||||
GNC_TEST_ADD( suitename, "qof object foreach sorted", Fixture, NULL, setup, test_qof_object_foreach_sorted, teardown );
|
||||
GNC_TEST_ADD( suitename, "qof object foreach backend", Fixture, NULL, setup, test_qof_object_foreach_backend, teardown );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user