gnucash master: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Sat Oct 29 16:20:26 EDT 2016
Updated via https://github.com/Gnucash/gnucash/commit/472b585f (commit)
via https://github.com/Gnucash/gnucash/commit/b8024fa9 (commit)
via https://github.com/Gnucash/gnucash/commit/00880cd8 (commit)
via https://github.com/Gnucash/gnucash/commit/70c803d6 (commit)
via https://github.com/Gnucash/gnucash/commit/afb57d0e (commit)
via https://github.com/Gnucash/gnucash/commit/0bc35eb3 (commit)
via https://github.com/Gnucash/gnucash/commit/10ff71b2 (commit)
via https://github.com/Gnucash/gnucash/commit/0baff455 (commit)
via https://github.com/Gnucash/gnucash/commit/7ff6e51a (commit)
via https://github.com/Gnucash/gnucash/commit/02d173d2 (commit)
via https://github.com/Gnucash/gnucash/commit/451f3ffe (commit)
via https://github.com/Gnucash/gnucash/commit/5065bce4 (commit)
via https://github.com/Gnucash/gnucash/commit/c1417114 (commit)
via https://github.com/Gnucash/gnucash/commit/5d38c7a7 (commit)
via https://github.com/Gnucash/gnucash/commit/314a5e10 (commit)
via https://github.com/Gnucash/gnucash/commit/00e0a6e8 (commit)
via https://github.com/Gnucash/gnucash/commit/fc47b632 (commit)
via https://github.com/Gnucash/gnucash/commit/61beed56 (commit)
via https://github.com/Gnucash/gnucash/commit/31c73a14 (commit)
via https://github.com/Gnucash/gnucash/commit/37d42573 (commit)
via https://github.com/Gnucash/gnucash/commit/5074bd59 (commit)
via https://github.com/Gnucash/gnucash/commit/b38be9fe (commit)
via https://github.com/Gnucash/gnucash/commit/d8556ca7 (commit)
via https://github.com/Gnucash/gnucash/commit/431b704c (commit)
via https://github.com/Gnucash/gnucash/commit/ccc1cc49 (commit)
via https://github.com/Gnucash/gnucash/commit/c2082bea (commit)
via https://github.com/Gnucash/gnucash/commit/54acef27 (commit)
via https://github.com/Gnucash/gnucash/commit/a303ae68 (commit)
via https://github.com/Gnucash/gnucash/commit/4b62deee (commit)
via https://github.com/Gnucash/gnucash/commit/cb464da5 (commit)
via https://github.com/Gnucash/gnucash/commit/885470b3 (commit)
via https://github.com/Gnucash/gnucash/commit/d1fd223f (commit)
via https://github.com/Gnucash/gnucash/commit/6f67e2dd (commit)
via https://github.com/Gnucash/gnucash/commit/d1063463 (commit)
via https://github.com/Gnucash/gnucash/commit/97b6e3a6 (commit)
via https://github.com/Gnucash/gnucash/commit/e0d5cc5b (commit)
via https://github.com/Gnucash/gnucash/commit/583c951a (commit)
via https://github.com/Gnucash/gnucash/commit/5823bf0d (commit)
via https://github.com/Gnucash/gnucash/commit/ccbfb69c (commit)
via https://github.com/Gnucash/gnucash/commit/c0a193c5 (commit)
via https://github.com/Gnucash/gnucash/commit/eed4a012 (commit)
via https://github.com/Gnucash/gnucash/commit/1f528392 (commit)
via https://github.com/Gnucash/gnucash/commit/3894a2e8 (commit)
via https://github.com/Gnucash/gnucash/commit/faf59964 (commit)
via https://github.com/Gnucash/gnucash/commit/7fe40480 (commit)
via https://github.com/Gnucash/gnucash/commit/cfa3ab24 (commit)
via https://github.com/Gnucash/gnucash/commit/12e76388 (commit)
via https://github.com/Gnucash/gnucash/commit/64c1fda6 (commit)
via https://github.com/Gnucash/gnucash/commit/92f2f276 (commit)
via https://github.com/Gnucash/gnucash/commit/6e84ccac (commit)
via https://github.com/Gnucash/gnucash/commit/e20c17b6 (commit)
via https://github.com/Gnucash/gnucash/commit/a716636e (commit)
via https://github.com/Gnucash/gnucash/commit/0d548da2 (commit)
via https://github.com/Gnucash/gnucash/commit/a0ae59a9 (commit)
via https://github.com/Gnucash/gnucash/commit/576bc8ae (commit)
via https://github.com/Gnucash/gnucash/commit/8078c41a (commit)
via https://github.com/Gnucash/gnucash/commit/2f0b5ec8 (commit)
via https://github.com/Gnucash/gnucash/commit/7e3ba421 (commit)
via https://github.com/Gnucash/gnucash/commit/7d4ca43f (commit)
via https://github.com/Gnucash/gnucash/commit/96a8a7b9 (commit)
via https://github.com/Gnucash/gnucash/commit/be1a5f56 (commit)
via https://github.com/Gnucash/gnucash/commit/72ac25d7 (commit)
via https://github.com/Gnucash/gnucash/commit/611f210a (commit)
via https://github.com/Gnucash/gnucash/commit/049b905d (commit)
from https://github.com/Gnucash/gnucash/commit/a808525d (commit)
commit 472b585feb3fd87ac41809a5c7e466ae335a40af
Merge: a808525 b8024fa
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Oct 29 13:16:29 2016 -0700
Interim merge of c++-backend to expose C++ interface.
commit b8024fa9eae3514cf1e7ba47463b2bb475dfbdc0
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Oct 29 12:40:57 2016 -0700
Fix review comment errors.
diff --git a/src/backend/dbi/gnc-dbisqlresult.cpp b/src/backend/dbi/gnc-dbisqlresult.cpp
index 07e7fa3..56e32bd 100644
--- a/src/backend/dbi/gnc-dbisqlresult.cpp
+++ b/src/backend/dbi/gnc-dbisqlresult.cpp
@@ -156,7 +156,7 @@ GncDbiSqlResult::IteratorImpl::get_time64_at_col (const char* col) const
auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
if (type != DBI_TYPE_DATETIME)
- throw (std::invalid_argument{"Requested double from non-double column."});
+ throw (std::invalid_argument{"Requested time64 from non-time64 column."});
gnc_push_locale (LC_NUMERIC, "C");
#if HAVE_LIBDBI_TO_LONGLONG
/* A less evil hack than the one equrie by libdbi-0.8, but
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index 1ba18bf..61cfb46 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -158,10 +158,10 @@ gnc_sql_get_object_backend(const std::string& type)
[type](const OBEEntry& entry){
return type == std::get<0>(entry);
});
- auto obe = std::get<1>(*entry);
- if (entry != backend_registry.end())
- return obe;
- return nullptr;
+ if (entry == backend_registry.end())
+ return nullptr;
+
+ return std::get<1>(*entry);
}
void
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 9b3ddbe..a81e114 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -355,7 +355,7 @@ protected:
* Row of SQL Query results.
*
* This is a "pointer" class of a pimpl pattern, the implementation being
- * GncSqlResul::IteratorImpl. It's designed to present a std::forward_iterator
+ * GncSqlResult::IteratorImpl. It's designed to present a std::forward_iterator
* like interface for use with range-for while allowing for wrapping a C API.
*
* Important Implementation Note: Operator++() as written requires that the
commit 00880cd8f505e80479fc97bc673db0e6050ed109
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Oct 29 11:42:55 2016 -0700
Fix another initializer list error.
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index c2c891b..9b3ddbe 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -418,7 +418,7 @@ public:
GncSqlObjectBackend (int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
m_table_name{table}, m_version{version}, m_type_name{type},
- m_col_table{vec} {}
+ m_col_table(vec) {}
/**
* Load all objects of m_type in the database into memory.
* @param be The GncSqlBackend containing the database connection.
commit 70c803d6aab75531c992014dee958c67745d741f
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Oct 28 12:56:13 2016 -0700
Fix unsigned-signed comparison mismatch.
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index cf1b1ab..66c8732 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -89,7 +89,7 @@ public:
GncSqlBackend(conn, book, format), m_exists{false} {}
bool connected() const noexcept { return m_conn != nullptr; }
/** FIXME: Just a pass-through to m_conn: */
- void set_error(int error, int repeat, bool retry) noexcept
+ void set_error(int error, unsigned int repeat, bool retry) noexcept
{
m_conn->set_error(error, repeat, retry);
}
diff --git a/src/backend/dbi/gnc-dbisqlconnection.hpp b/src/backend/dbi/gnc-dbisqlconnection.hpp
index b97520f..fd33294 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.hpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.hpp
@@ -58,7 +58,8 @@ public:
return dbi_conn_error(m_conn, nullptr); }
QofBackend* qbe () const noexcept { return m_qbe; }
dbi_conn conn() const noexcept { return m_conn; }
- inline void set_error(int error, int repeat, bool retry) noexcept override
+ inline void set_error(int error, unsigned int repeat,
+ bool retry) noexcept override
{
m_last_error = error;
m_error_repeat = repeat;
@@ -96,7 +97,7 @@ private:
* the original call is allowed. error_repeat tracks the number of attempts
* and can be used to prevent infinite loops.
*/
- int m_error_repeat;
+ unsigned int m_error_repeat;
/** Signals the calling function that it should retry (the error handler
* detected transient error and managed to resolve it, but it can't run the
* original query)
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index cdf72fc..c2c891b 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -313,7 +313,7 @@ public:
* If not 0 will normally be meaningless outside of implementation code.
*/
virtual int dberror() const noexcept = 0;
- virtual void set_error(int error, int repeat, bool retry) noexcept = 0;
+ virtual void set_error(int error, unsigned int repeat, bool retry) noexcept = 0;
virtual bool verify() noexcept = 0;
virtual bool retry_connection(const char* msg) noexcept = 0;
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index f2922c1..f968a91 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -105,7 +105,7 @@ public:
virtual std::string quote_string (const std::string& str)
const noexcept override { return std::string{str}; }
int dberror() const noexcept override { return 0; }
- void set_error(int error, int repeat, bool retry) noexcept override { return; }
+ void set_error(int error, unsigned int repeat, bool retry) noexcept override { return; }
bool verify() noexcept override { return true; }
bool retry_connection(const char* msg) noexcept override { return true; }
private:
commit afb57d0e7b86a19b58baddcddd00d727fc0041b7
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Oct 28 12:31:49 2016 -0700
Initialize a variable to appease travis-ci.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 23a0fa9..c8fffc9 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -308,7 +308,7 @@ conn_setup (QofBackend* qbe, PairVec& options,
const char* dbstr = (Type == DbType::DBI_SQLITE ? "sqlite3" :
Type == DbType::DBI_MYSQL ? "mysql" : "pgsql");
#if HAVE_LIBDBI_R
- dbi_conn conn;
+ dbi_conn conn = nullptr;
if (dbi_instance)
conn = dbi_conn_new_r (dbstr, dbi_instance);
else
commit 0bc35eb3e28288858bb208c4067021f8343dbc6d
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Oct 28 11:38:29 2016 -0700
Fix two C++11 initializer list errors.
diff --git a/src/backend/sql/gnc-address-sql.cpp b/src/backend/sql/gnc-address-sql.cpp
index cd6dd70..0c280c0 100644
--- a/src/backend/sql/gnc-address-sql.cpp
+++ b/src/backend/sql/gnc-address-sql.cpp
@@ -129,7 +129,7 @@ GncSqlColumnTableEntryImpl<CT_ADDRESS>::add_to_query(const GncSqlBackend* be,
const gpointer pObject,
PairVec& vec) const noexcept
{
- auto addr{get_row_value_from_object<char*>(obj_name, pObject)};
+ auto addr(get_row_value_from_object<char*>(obj_name, pObject));
if (addr == nullptr) return;
for (auto const& subtable_row : col_table)
@@ -139,7 +139,7 @@ GncSqlColumnTableEntryImpl<CT_ADDRESS>::add_to_query(const GncSqlBackend* be,
if (s == nullptr)
continue;
auto buf = std::string{m_col_name} + "_" + subtable_row->m_col_name;
- vec.emplace_back(make_pair(buf, std::string{s}));
+ vec.emplace_back(make_pair(buf, std::string(s)));
}
}
/* ========================== END OF FILE ===================== */
commit 10ff71b29a430ccfc166129ceb20372534245cee
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Oct 25 14:15:43 2016 -0700
Fix passing std::string to PWARN.
diff --git a/src/backend/dbi/gnc-dbiproviderimpl.hpp b/src/backend/dbi/gnc-dbiproviderimpl.hpp
index e79003c..4c3f449 100644
--- a/src/backend/dbi/gnc-dbiproviderimpl.hpp
+++ b/src/backend/dbi/gnc-dbiproviderimpl.hpp
@@ -305,7 +305,7 @@ GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
PWARN ("Index Table Retrieval Error: %s on table %s\n",
- errmsg, table_name);
+ errmsg, table_name.c_str());
continue;
}
commit 0baff455a2b60d049f9dd2cf6bbf5e9a510a49c2
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Aug 9 10:05:33 2016 -0700
Bug 769115 - db name isn't escaped well
More like at all, but it's supposed to be quoted rather than
escaped.
dbi_conn_quote_string() doesn't work well for database names,
so we do it directly. libdbi is also inconsistent about needing
quotes: They're required by mysql in SQL commands, and libdbi
requires them for internal commands that it turns into SQL
(e.g. db_conn_get_table_list) but not others (e.g dbi_conn_set_option).
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 17830c7..23a0fa9 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -112,7 +112,7 @@ constexpr const char* MYSQL_TIMESPEC_STR_FORMAT = "%04d%02d%02d%02d%02d%02d";
constexpr const char* PGSQL_TIMESPEC_STR_FORMAT = "%04d%02d%02d %02d%02d%02d";
static void adjust_sql_options (dbi_conn connection);
-static bool save_may_clobber_data (dbi_conn conn);
+static bool save_may_clobber_data (dbi_conn conn, const std::string& dbname);
static void init_sql_backend (GncDbiBackend* dbi_be);
static bool conn_test_dbi_library (dbi_conn conn, QofBackend* qbe);
@@ -175,6 +175,7 @@ struct UriStrings
~UriStrings() = default;
std::string basename() const noexcept;
const char* dbname() const noexcept;
+ std::string quote_dbname(DbType t) const noexcept;
std::string m_protocol;
std::string m_host;
std::string m_dbname;
@@ -201,6 +202,7 @@ UriStrings::UriStrings(const std::string& uri)
g_free(username);
g_free(password);
g_free(dbname);
+
}
std::string
@@ -215,6 +217,17 @@ UriStrings::dbname() const noexcept
return m_dbname.c_str();
}
+std::string
+UriStrings::quote_dbname(DbType t) const noexcept
+{
+ if (m_dbname.empty())
+ return "";
+ const char quote = (t == DbType::DBI_MYSQL ? '`' : '"');
+ std::string retval(1, quote);
+ retval += m_dbname + quote;
+ return retval;
+}
+
static void
create_tables(const OBEEntry& entry, GncDbiBackend* be)
{
@@ -312,7 +325,6 @@ conn_setup (QofBackend* qbe, PairVec& options,
}
dbi_conn_error_handler (conn, error_handler<Type>, qbe);
-
if (!uri.m_dbname.empty() &&
!set_standard_connection_options(qbe, conn, uri))
{
@@ -674,7 +686,8 @@ gnc_dbi_session_begin (QofBackend* qbe, QofSession* session,
LEAVE("Error");
return;
}
- if (create && !force && save_may_clobber_data (conn))
+ if (create && !force && save_may_clobber_data (conn,
+ uri.quote_dbname(T)))
{
qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
PWARN ("Databse already exists, Might clobber it.");
@@ -698,7 +711,7 @@ gnc_dbi_session_begin (QofBackend* qbe, QofSession* session,
if (create)
{
- if (!create_database(T, qbe, conn, uri.dbname()))
+ if (!create_database(T, qbe, conn, uri.quote_dbname(T).c_str()))
{
dbi_conn_close(conn);
LEAVE("Error");
@@ -720,7 +733,8 @@ gnc_dbi_session_begin (QofBackend* qbe, QofSession* session,
{
if (T == DbType::DBI_PGSQL)
dbi_conn_select_db (conn, "template1");
- dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
+ dbi_conn_queryf (conn, "DROP DATABASE %s",
+ uri.quote_dbname(T).c_str());
dbi_conn_close(conn);
return;
}
@@ -883,14 +897,13 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
}
/* ================================================================= */
-
+/* This is used too early to call GncDbiProvider::get_table_list(). */
static bool
-save_may_clobber_data (dbi_conn conn)
+save_may_clobber_data (dbi_conn conn, const std::string& dbname)
{
/* Data may be clobbered iff the number of tables != 0 */
- auto dbname = dbi_conn_get_option (conn, "dbname");
- auto result = dbi_conn_get_table_list (conn, dbname, nullptr);
+ auto result = dbi_conn_get_table_list (conn, dbname.c_str(), nullptr);
bool retval = false;
if (result)
{
diff --git a/src/backend/dbi/gnc-dbiproviderimpl.hpp b/src/backend/dbi/gnc-dbiproviderimpl.hpp
index 9158de5..e79003c 100644
--- a/src/backend/dbi/gnc-dbiproviderimpl.hpp
+++ b/src/backend/dbi/gnc-dbiproviderimpl.hpp
@@ -245,6 +245,8 @@ GncDbiProviderImpl<DbType::DBI_MYSQL>::get_table_list (dbi_conn conn,
const std::string& table)
{
std::string dbname (dbi_conn_get_option (conn, "dbname"));
+ dbname.insert((std::string::size_type)0, 1, '`');
+ dbname += '`';
return conn_get_table_list (conn, dbname, table);
}
commit 7ff6e51a725cbeddb9d3e0f99d4ec42c0653d448
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Aug 9 09:30:46 2016 -0700
Use GncDbiProvider::get_table_list instead of calling out to libdbi.
GncDbiProvider can figure out the dbname for itself so change the
function signature to replace dbname with a particular table to
search for. Pass an empty string ("" works) to get the full list.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 9d1dae0..17830c7 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -921,8 +921,7 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
g_return_if_fail (book != nullptr);
ENTER ("book=%p, primary=%p", book, be->m_book);
- auto dbname = dbi_conn_get_option (conn->conn(), "dbname");
- auto table_list = conn->m_provider->get_table_list (conn->conn(), dbname);
+ auto table_list = conn->m_provider->get_table_list (conn->conn(), "");
if (!conn->table_operation (table_list, backup))
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
diff --git a/src/backend/dbi/gnc-dbiprovider.hpp b/src/backend/dbi/gnc-dbiprovider.hpp
index e0a2561..2f168d8 100644
--- a/src/backend/dbi/gnc-dbiprovider.hpp
+++ b/src/backend/dbi/gnc-dbiprovider.hpp
@@ -42,7 +42,7 @@ class GncDbiProvider
{
public:
virtual ~GncDbiProvider() = default;
- virtual StrVec get_table_list(dbi_conn conn, const std::string& dbname) = 0;
+ virtual StrVec get_table_list(dbi_conn conn, const std::string& table) = 0;
virtual void append_col_def(std::string& ddl,
const GncSqlColumnInfo& info) = 0;
virtual StrVec get_index_list (dbi_conn conn) = 0;
diff --git a/src/backend/dbi/gnc-dbiproviderimpl.hpp b/src/backend/dbi/gnc-dbiproviderimpl.hpp
index a96461b..9158de5 100644
--- a/src/backend/dbi/gnc-dbiproviderimpl.hpp
+++ b/src/backend/dbi/gnc-dbiproviderimpl.hpp
@@ -34,7 +34,7 @@ template <DbType T>
class GncDbiProviderImpl : public GncDbiProvider
{
public:
- StrVec get_table_list(dbi_conn conn, const std::string& dbname);
+ StrVec get_table_list(dbi_conn conn, const std::string& table);
void append_col_def(std::string& ddl, const GncSqlColumnInfo& info);
StrVec get_index_list (dbi_conn conn);
void drop_index(dbi_conn conn, const std::string& index);
@@ -212,10 +212,12 @@ GncDbiProviderImpl<DbType::DBI_PGSQL>::append_col_def (std::string& ddl,
}
static StrVec
-conn_get_table_list (dbi_conn conn, const std::string& dbname)
+conn_get_table_list (dbi_conn conn, const std::string& dbname,
+ const std::string& table)
{
StrVec retval;
- auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), nullptr);
+ const char* tableptr = (table.empty() ? nullptr : table.c_str());
+ auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), tableptr);
while (dbi_result_next_row (tables) != 0)
{
std::string table_name {dbi_result_get_string_idx (tables, 1)};
@@ -227,11 +229,12 @@ conn_get_table_list (dbi_conn conn, const std::string& dbname)
template<> StrVec
GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
- const std::string& dbname)
+ const std::string& table)
{
/* Return the list, but remove the tables that sqlite3 adds for
* its own use. */
- auto list = conn_get_table_list (conn, dbname);
+ std::string dbname (dbi_conn_get_option (conn, "dbname"));
+ auto list = conn_get_table_list (conn, dbname, table);
auto end = std::remove(list.begin(), list.end(), "sqlite_sequence");
list.erase(end, list.end());
return list;
@@ -239,16 +242,18 @@ GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
template<> StrVec
GncDbiProviderImpl<DbType::DBI_MYSQL>::get_table_list (dbi_conn conn,
- const std::string& dbname)
+ const std::string& table)
{
- return conn_get_table_list (conn, dbname);
+ std::string dbname (dbi_conn_get_option (conn, "dbname"));
+ return conn_get_table_list (conn, dbname, table);
}
template<> StrVec
GncDbiProviderImpl<DbType::DBI_PGSQL>::get_table_list (dbi_conn conn,
- const std::string& dbname)
+ const std::string& table)
{
- auto list = conn_get_table_list (conn, dbname);
+ std::string dbname (dbi_conn_get_option (conn, "dbname"));
+ auto list = conn_get_table_list (conn, dbname, table);
auto end = std::remove_if (list.begin(), list.end(),
[](std::string& table_name){
return table_name == "sql_features" ||
@@ -289,19 +294,12 @@ GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
{
StrVec retval;
const char* errmsg;
- auto dbname = dbi_conn_get_option (conn, "dbname");
- auto table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
- if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
- {
- PWARN ("Table Retrieval Error: %s\n", errmsg);
- return retval;
- }
- while (dbi_result_next_row (table_list) != 0)
+ auto tables = get_table_list(conn, "");
+ for (auto table_name : tables)
{
- auto table_name = dbi_result_get_string_idx (table_list, 1);
auto result = dbi_conn_queryf (conn,
"SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
- table_name);
+ table_name.c_str());
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
PWARN ("Index Table Retrieval Error: %s on table %s\n",
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index aa9d378..c785ac8 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -35,7 +35,7 @@ static QofLogModule log_module = G_LOG_DOMAIN;
#include "gnc-dbiproviderimpl.hpp"
static const unsigned int DBI_MAX_CONN_ATTEMPTS = 5;
-constexpr const char *lock_table_name = "gnclock";
+const std::string lock_table = "gnclock";
/* --------------------------------------------------------- */
class GncDbiSqlStatement : public GncSqlStatement
@@ -91,22 +91,14 @@ GncDbiSqlConnection::GncDbiSqlConnection (DbType type, QofBackend* qbe,
bool
GncDbiSqlConnection::lock_database (bool ignore_lock)
{
-
- auto dbname = dbi_conn_get_option (m_conn, "dbname");
- /* Create the table if it doesn't exist */
- auto result = dbi_conn_get_table_list (m_conn, dbname, lock_table_name);
- int numrows = 0;
- const char* errstr;
- if (result) {
- numrows = dbi_result_get_numrows (result);
- dbi_result_free (result);
- result = nullptr;
- }
- if (numrows == 0)
- {
- result = dbi_conn_queryf (m_conn,
- "CREATE TABLE %s ( Hostname varchar(%d), PID int )", lock_table_name,
- GNC_HOST_NAME_MAX);
+ const char *errstr;
+ auto tables = m_provider->get_table_list(m_conn, lock_table);
+ if (tables.empty())
+ {
+ auto result = dbi_conn_queryf (m_conn,
+ "CREATE TABLE %s ( Hostname varchar(%d), PID int )",
+ lock_table.c_str(),
+ GNC_HOST_NAME_MAX);
if (result)
{
dbi_result_free (result);
@@ -121,7 +113,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
}
/* Protect everything with a single transaction to prevent races */
- result = dbi_conn_query (m_conn, "BEGIN");
+ auto result = dbi_conn_query (m_conn, "BEGIN");
if (dbi_conn_error (m_conn, &errstr))
{
/* Couldn't get a transaction (probably couldn't get a lock), so fail */
@@ -135,7 +127,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
result = nullptr;
/* Check for an existing entry; delete it if ignore_lock is true, otherwise fail */
char hostname[ GNC_HOST_NAME_MAX + 1 ];
- result = dbi_conn_queryf (m_conn, "SELECT * FROM %s", lock_table_name);
+ result = dbi_conn_queryf (m_conn, "SELECT * FROM %s", lock_table.c_str());
if (result && dbi_result_get_numrows (result))
{
dbi_result_free (result);
@@ -147,7 +139,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
dbi_conn_query (m_conn, "ROLLBACK");
return false;
}
- result = dbi_conn_queryf (m_conn, "DELETE FROM %s", lock_table_name);
+ result = dbi_conn_queryf (m_conn, "DELETE FROM %s", lock_table.c_str());
if (!result)
{
qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
@@ -165,7 +157,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
gethostname (hostname, GNC_HOST_NAME_MAX);
result = dbi_conn_queryf (m_conn,
"INSERT INTO %s VALUES ('%s', '%d')",
- lock_table_name, hostname, (int)GETPID ());
+ lock_table.c_str(), hostname, (int)GETPID ());
if (!result)
{
qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
@@ -198,23 +190,13 @@ GncDbiSqlConnection::unlock_database ()
if (m_conn == nullptr) return;
g_return_if_fail (dbi_conn_error (m_conn, nullptr) == 0);
- auto dbname = dbi_conn_get_option (m_conn, "dbname");
- /* Check if the lock table exists */
- g_return_if_fail (dbname != nullptr);
- auto result = dbi_conn_get_table_list (m_conn, dbname, lock_table_name);
- if (! (result && dbi_result_get_numrows (result)))
+ auto tables = m_provider->get_table_list (m_conn, lock_table);
+ if (tables.empty())
{
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
PWARN ("No lock table in database, so not unlocking it.");
return;
}
- dbi_result_free (result);
-
- result = dbi_conn_query (m_conn, "BEGIN");
+ auto result = dbi_conn_query (m_conn, "BEGIN");
if (result)
{
/* Delete the entry if it's our hostname and PID */
@@ -225,7 +207,7 @@ GncDbiSqlConnection::unlock_database ()
memset (hostname, 0, sizeof (hostname));
gethostname (hostname, GNC_HOST_NAME_MAX);
result = dbi_conn_queryf (m_conn,
- "SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", lock_table_name, hostname,
+ "SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", lock_table.c_str(), hostname,
(int)GETPID ());
if (result && dbi_result_get_numrows (result))
{
@@ -234,7 +216,8 @@ GncDbiSqlConnection::unlock_database ()
dbi_result_free (result);
result = nullptr;
}
- result = dbi_conn_queryf (m_conn, "DELETE FROM %s", lock_table_name);
+ result = dbi_conn_queryf (m_conn, "DELETE FROM %s",
+ lock_table.c_str());
if (!result)
{
PERR ("Failed to delete the lock entry");
@@ -349,17 +332,7 @@ bool
GncDbiSqlConnection::does_table_exist (const std::string& table_name)
const noexcept
{
- auto dbname = dbi_conn_get_option (m_conn, "dbname");
- auto tables = dbi_conn_get_table_list (m_conn, dbname, table_name.c_str());
- auto nTables = dbi_result_get_numrows (tables);
- auto status = dbi_result_free (tables);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
-
- return nTables == 1;
+ return ! m_provider->get_table_list(m_conn, table_name).empty();
}
bool
@@ -660,8 +633,6 @@ bool
GncDbiSqlConnection::table_operation(const StrVec& table_names,
TableOpType op) noexcept
{
- const char* dbname = dbi_conn_get_option (m_conn, "dbname");
- std::string lock_table{lock_table_name};
g_return_val_if_fail (!table_names.empty(), FALSE);
bool retval{true};
for (auto table : table_names)
@@ -679,7 +650,7 @@ GncDbiSqlConnection::table_operation(const StrVec& table_names,
{
case rollback:
{
- auto all_tables = m_provider->get_table_list(m_conn, dbname);
+ auto all_tables = m_provider->get_table_list(m_conn, "");
if (std::find(all_tables.begin(),
all_tables.end(), table) != all_tables.end())
{
commit 02d173d2e781d371d6648a2a97e58a19efc5de4e
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Jul 29 14:23:36 2016 -0700
Replace g_str functions in dbi_library_test with std::stringstream.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index dbaa767..9d1dae0 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -44,6 +44,7 @@ extern "C"
#include <windows.h>
#endif
+#include <inttypes.h>
#include <errno.h>
#include <glib.h>
#include <glib/gstdio.h>
@@ -71,6 +72,7 @@ extern "C"
}
#include <boost/regex.hpp>
#include <string>
+#include <iomanip>
#include <gnc-backend-prov.hpp>
#include "gnc-backend-dbi.h"
@@ -479,7 +481,9 @@ gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session,
conn = nullptr;
g_unlink (filepath.c_str());
}
+ dbi_conn_close(conn);
LEAVE("Bad DBI Library");
+ return;
}
try
@@ -1208,9 +1212,7 @@ dbi_library_test (dbi_conn conn)
uint64_t testulonglong = 9223372036854775807LLU, resultulonglong = 0;
double testdouble = 1.7976921348623157E+307, resultdouble = 0.0;
dbi_result result;
- char doublestr[G_ASCII_DTOSTR_BUF_SIZE], *querystr;
GncDbiTestResult retval = GNC_DBI_PASS;
- memset (doublestr, 0, sizeof (doublestr));
result = dbi_conn_query (conn, "CREATE TEMPORARY TABLE numtest "
"( test_int BIGINT, test_unsigned BIGINT,"
@@ -1221,12 +1223,12 @@ dbi_library_test (dbi_conn conn)
return GNC_DBI_FAIL_SETUP;
}
dbi_result_free (result);
- g_ascii_dtostr (doublestr, sizeof (doublestr), testdouble);
- querystr = g_strdup_printf ("INSERT INTO numtest VALUES (%" G_GINT64_FORMAT
- ", %" G_GUINT64_FORMAT ", %s)",
- testlonglong, testulonglong, doublestr);
- result = dbi_conn_query (conn, querystr);
- g_free (querystr);
+ std::stringstream querystr;
+ querystr << "INSERT INTO numtest VALUES (" << testlonglong <<
+ ", " << testulonglong << ", " << std::setprecision(12) <<
+ testdouble << ")";
+ auto query = querystr.str();
+ result = dbi_conn_query (conn, query.c_str());
if (result == nullptr)
{
PWARN ("Test_DBI_Library: Failed to insert test row into table");
@@ -1254,16 +1256,14 @@ dbi_library_test (dbi_conn conn)
gnc_pop_locale (LC_NUMERIC);
if (testlonglong != resultlonglong)
{
- PWARN ("Test_DBI_Library: LongLong Failed %" G_GINT64_FORMAT " != % "
- G_GINT64_FORMAT,
+ PWARN ("Test_DBI_Library: LongLong Failed %" PRId64 " != % " PRId64,
testlonglong, resultlonglong);
retval = GNC_DBI_FAIL_TEST;
}
if (testulonglong != resultulonglong)
{
- PWARN ("Test_DBI_Library: Unsigned longlong Failed %" G_GUINT64_FORMAT " != %"
- G_GUINT64_FORMAT,
- testulonglong, resultulonglong);
+ PWARN ("Test_DBI_Library: Unsigned longlong Failed %" PRIu64 " != %"
+ PRIu64, testulonglong, resultulonglong);
retval = GNC_DBI_FAIL_TEST;
}
/* A bug in libdbi stores only 7 digits of precision */
commit 451f3ffe4df5229d0fe597ec52a0b28dd3ecf382
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Jul 29 13:36:45 2016 -0700
DBI: Convert all of the gchar to char, remove a few gratuitous g_funcs.
Except where we're explicitly using other GLib functions.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index ae22fca..dbaa767 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -117,7 +117,7 @@ static bool conn_test_dbi_library (dbi_conn conn, QofBackend* qbe);
template <DbType T> void gnc_dbi_session_begin(QofBackend* qbe,
QofSession* session,
- const gchar* book_id,
+ const char* book_id,
gboolean ignore_lock,
gboolean create, gboolean force);
template <DbType Type> QofBackend*
@@ -138,7 +138,7 @@ new_backend ()
break;
}
auto dbi_be = new GncDbiBackend(nullptr, nullptr, format);
- g_assert (dbi_be != nullptr);
+ assert (dbi_be != nullptr);
be = (QofBackend*)dbi_be;
qof_backend_init (be);
@@ -390,7 +390,7 @@ create_database(DbType type, QofBackend *qbe, dbi_conn conn, const char* db)
template <> void
error_handler<DbType::DBI_SQLITE> (dbi_conn conn, void* user_data)
{
- const gchar* msg;
+ const char* msg;
GncDbiBackend *be = static_cast<decltype(be)>(user_data);
int errnum = dbi_conn_error (conn, &msg);
PERR ("DBI error: %s\n", msg);
@@ -400,7 +400,7 @@ error_handler<DbType::DBI_SQLITE> (dbi_conn conn, void* user_data)
template <> void
gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session,
- const gchar* book_id, gboolean ignore_lock,
+ const char* book_id, gboolean ignore_lock,
gboolean create, gboolean force)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
@@ -619,7 +619,7 @@ adjust_sql_options (dbi_conn connection)
template <DbType T> void
gnc_dbi_session_begin (QofBackend* qbe, QofSession* session,
- const gchar* book_id, gboolean ignore_lock,
+ const char* book_id, gboolean ignore_lock,
gboolean create, gboolean force)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
@@ -751,7 +751,7 @@ template<> void
error_handler<DbType::DBI_PGSQL> (dbi_conn conn, void* user_data)
{
GncDbiBackend* be = (GncDbiBackend*)user_data;
- const gchar* msg;
+ const char* msg;
(void)dbi_conn_error (conn, &msg);
if (g_str_has_prefix (msg, "FATAL: database") &&
@@ -848,7 +848,7 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
// Set up table version information
be->init_version_info ();
- g_assert (be->m_book == nullptr);
+ assert (be->m_book == nullptr);
// Call all object backends to create any required tables
auto registry = gnc_sql_get_backend_registry();
@@ -1061,7 +1061,7 @@ QofDbiBackendProvider<DbType::DBI_SQLITE>::type_check(const char *uri)
void
gnc_module_init_backend_dbi (void)
{
- const gchar* driver_dir;
+ const char* driver_dir;
int num_drivers;
gboolean have_sqlite3_driver = FALSE;
gboolean have_mysql_driver = FALSE;
@@ -1204,11 +1204,11 @@ gnc_module_finalize_backend_dbi (void)
static GncDbiTestResult
dbi_library_test (dbi_conn conn)
{
- gint64 testlonglong = -9223372036854775807LL, resultlonglong = 0;
- guint64 testulonglong = 9223372036854775807LLU, resultulonglong = 0;
- gdouble testdouble = 1.7976921348623157E+307, resultdouble = 0.0;
+ int64_t testlonglong = -9223372036854775807LL, resultlonglong = 0;
+ uint64_t testulonglong = 9223372036854775807LLU, resultulonglong = 0;
+ double testdouble = 1.7976921348623157E+307, resultdouble = 0.0;
dbi_result result;
- gchar doublestr[G_ASCII_DTOSTR_BUF_SIZE], *querystr;
+ char doublestr[G_ASCII_DTOSTR_BUF_SIZE], *querystr;
GncDbiTestResult retval = GNC_DBI_PASS;
memset (doublestr, 0, sizeof (doublestr));
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index 3f68e1e..aa9d378 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -218,7 +218,7 @@ GncDbiSqlConnection::unlock_database ()
if (result)
{
/* Delete the entry if it's our hostname and PID */
- gchar hostname[ GNC_HOST_NAME_MAX + 1 ];
+ char hostname[ GNC_HOST_NAME_MAX + 1 ];
dbi_result_free (result);
result = nullptr;
@@ -541,7 +541,7 @@ std::string
GncDbiSqlConnection::quote_string (const std::string& unquoted_str)
const noexcept
{
- gchar* quoted_str;
+ char* quoted_str;
size_t size;
size = dbi_conn_quote_string_copy (m_conn, unquoted_str.c_str(),
commit 5065bce45c39c6281904139b63954947c3bdf552
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Jul 29 13:29:51 2016 -0700
Combine Postgres and MySql gnc_dbi_session_begin into a single template.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index ad5f034..ae22fca 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -482,7 +482,6 @@ gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session,
LEAVE("Bad DBI Library");
}
- be->connect(nullptr);
try
{
be->connect(new GncDbiSqlConnection(DbType::DBI_SQLITE,
@@ -618,8 +617,8 @@ adjust_sql_options (dbi_conn connection)
}
-template <> void
-gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
+template <DbType T> void
+gnc_dbi_session_begin (QofBackend* qbe, QofSession* session,
const gchar* book_id, gboolean ignore_lock,
gboolean create, gboolean force)
{
@@ -638,9 +637,21 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
where username, password and port are optional) */
UriStrings uri(book_id);
+ if (T == DbType::DBI_PGSQL)
+ {
+ if (uri.m_portnum == 0)
+ uri.m_portnum = PGSQL_DEFAULT_PORT;
+ /* Postgres's SQL interface coerces identifiers to lower case, but the
+ * C interface is case-sensitive. This results in a mixed-case dbname
+ * being created (with a lower case name) but then dbi can't conect to
+ * it. To work around this, coerce the name to lowercase first. */
+ auto lcname = g_utf8_strdown (uri.dbname(), -1);
+ uri.m_dbname = std::string{lcname};
+ g_free(lcname);
+ }
be->connect(nullptr);
- auto conn = conn_setup<DbType::DBI_MYSQL>(qbe, options, uri);
+ auto conn = conn_setup<T>(qbe, options, uri);
if (conn == nullptr)
{
LEAVE("Error");
@@ -651,9 +662,11 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
auto result = dbi_conn_connect (conn);
if (result == 0)
{
- adjust_sql_options (conn);
+ if (T == DbType::DBI_MYSQL)
+ adjust_sql_options (conn);
if(!conn_test_dbi_library(conn, qbe))
{
+ dbi_conn_close(conn);
LEAVE("Error");
return;
}
@@ -661,6 +674,7 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
{
qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
PWARN ("Databse already exists, Might clobber it.");
+ dbi_conn_close(conn);
LEAVE("Error");
return;
}
@@ -673,30 +687,37 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to connect to database '%s'\n", uri.dbname());
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
+ dbi_conn_close(conn);
LEAVE("Error");
return;
}
if (create)
{
- if (!create_database(DbType::DBI_MYSQL, qbe, conn, uri.dbname()))
+ if (!create_database(T, qbe, conn, uri.dbname()))
{
+ dbi_conn_close(conn);
LEAVE("Error");
return;
}
- conn = conn_setup<DbType::DBI_MYSQL>(qbe, options, uri);
+ conn = conn_setup<T>(qbe, options, uri);
result = dbi_conn_connect (conn);
if (result < 0)
{
PERR ("Unable to create database '%s'\n", uri.dbname());
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
+ dbi_conn_close(conn);
LEAVE("Error");
return;
}
- adjust_sql_options (conn);
+ if (T == DbType::DBI_MYSQL)
+ adjust_sql_options (conn);
if (!conn_test_dbi_library(conn, qbe))
{
+ if (T == DbType::DBI_PGSQL)
+ dbi_conn_select_db (conn, "template1");
dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
+ dbi_conn_close(conn);
return;
}
}
@@ -710,8 +731,7 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
be->connect(nullptr);
try
{
- be->connect(new GncDbiSqlConnection(DbType::DBI_MYSQL,
- qbe, conn, ignore_lock));
+ be->connect(new GncDbiSqlConnection(T, qbe, conn, ignore_lock));
}
catch (std::runtime_error& err)
{
@@ -772,124 +792,6 @@ error_handler<DbType::DBI_PGSQL> (dbi_conn conn, void* user_data)
}
}
-template <>void
-gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
- const gchar* book_id, gboolean ignore_lock,
- gboolean create, gboolean force)
-{
- GncDbiBackend* be = (GncDbiBackend*)qbe;
- bool success = false;
- PairVec options;
-
- g_return_if_fail (qbe != nullptr);
- g_return_if_fail (session != nullptr);
- g_return_if_fail (book_id != nullptr);
-
- ENTER (" ");
-
- /* Split the book-id
- * Format is protocol://username:password@hostname:port/dbname
- where username, password and port are optional) */
- UriStrings uri(book_id);
- if (uri.m_portnum == 0)
- uri.m_portnum = PGSQL_DEFAULT_PORT;
- /* Postgres's SQL interface coerces identifiers to lower case, but the
- * C interface is case-sensitive. This results in a mixed-case dbname
- * being created (with a lower case name) but then dbi can't conect to
- * it. To work around this, coerce the name to lowercase first. */
- auto lcname = g_utf8_strdown (uri.dbname(), -1);
- uri.m_dbname = std::string{lcname};
- g_free(lcname);
- be->connect(nullptr);
-
- auto conn = conn_setup<DbType::DBI_PGSQL>(qbe, options, uri);
- if (conn == nullptr)
- {
- LEAVE("Error");
- return;
- }
-
- be->set_exists(true); //May be unset in the error handler.
- auto result = dbi_conn_connect (conn);
- if (result == 0)
- {
- if (!conn_test_dbi_library(conn, qbe))
- {
- LEAVE("Error");
- return;
- }
- if (create && !force && save_may_clobber_data(conn))
- {
- qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
- PWARN ("Databse already exists, Might clobber it.");
- LEAVE("Error");
- return;
- }
-
- }
- else
- {
-
- if (be->exists())
- {
- PERR ("Unable to connect to database '%s'\n", uri.dbname());
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- LEAVE("Error");
- return;
- }
-
- if (create)
- {
- if (!create_database(DbType::DBI_PGSQL, qbe, conn, uri.dbname()))
- {
- LEAVE("Error");
- return;
- }
- conn = conn_setup<DbType::DBI_PGSQL>(qbe, options, uri);
- result = dbi_conn_connect (conn);
- if (result < 0)
- {
- PERR ("Unable to create database '%s'\n", uri.dbname());
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- LEAVE("Error");
- return;
- }
- if (!conn_test_dbi_library(conn, qbe))
- {
- dbi_conn_select_db (conn, "template1");
- dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
- LEAVE("Error");
- return;
- }
- }
- else
- {
- qof_backend_set_error (qbe, ERR_BACKEND_NO_SUCH_DB);
- qof_backend_set_message (qbe, "Database %s not found", uri.dbname());
- }
- }
- be->connect(nullptr);
- try
- {
- be->connect(new GncDbiSqlConnection(DbType::DBI_PGSQL,
- qbe, conn, ignore_lock));
- }
- catch (std::runtime_error& err)
- {
- return;
- }
-
- /* We should now have a proper session set up.
- * Let's start logging */
- auto translog_path = gnc_build_translog_path (uri.basename().c_str());
- xaccLogSetBaseName (translog_path);
- PINFO ("logpath=%s", translog_path ? translog_path : "(null)");
- g_free (translog_path);
-
- LEAVE (" ");
-}
-
-
/* ================================================================= */
static void
commit c141711425fd337aaa24efc4eca4c5702a89b5ba
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Jul 29 13:10:40 2016 -0700
Move creation of the provider to GncDbiSqlConnection's constructor.
Making GncDbiProviderImpl private to GncDbiSqlConnection.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index afff942..ad5f034 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -98,8 +98,6 @@ static dbi_inst dbi_instance = nullptr;
#define TRANSACTION_NAME "trans"
static QofLogModule log_module = G_LOG_DOMAIN;
-// gnc-dbiproviderimpl.hpp has templates that need log_module defined.
-#include "gnc-dbiproviderimpl.hpp"
#define FILE_URI_TYPE "file"
#define FILE_URI_PREFIX (FILE_URI_TYPE "://")
@@ -288,7 +286,7 @@ set_standard_connection_options (QofBackend* qbe, dbi_conn conn,
template <DbType Type> void error_handler(void* conn, void* data);
void error_handler(void* conn, void* data);
-template <DbType Type>dbi_conn
+template <DbType Type> dbi_conn
conn_setup (QofBackend* qbe, PairVec& options,
UriStrings& uri)
{
@@ -487,7 +485,7 @@ gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session,
be->connect(nullptr);
try
{
- be->connect(new GncDbiSqlConnection(make_dbi_provider<DbType::DBI_SQLITE>(),
+ be->connect(new GncDbiSqlConnection(DbType::DBI_SQLITE,
qbe, conn, ignore_lock));
}
catch (std::runtime_error& err)
@@ -712,7 +710,7 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
be->connect(nullptr);
try
{
- be->connect(new GncDbiSqlConnection(make_dbi_provider<DbType::DBI_MYSQL>(),
+ be->connect(new GncDbiSqlConnection(DbType::DBI_MYSQL,
qbe, conn, ignore_lock));
}
catch (std::runtime_error& err)
@@ -873,7 +871,7 @@ gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
be->connect(nullptr);
try
{
- be->connect(new GncDbiSqlConnection(make_dbi_provider<DbType::DBI_PGSQL>(),
+ be->connect(new GncDbiSqlConnection(DbType::DBI_PGSQL,
qbe, conn, ignore_lock));
}
catch (std::runtime_error& err)
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index 98b9617..3f68e1e 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -31,6 +31,8 @@ extern "C"
#include "gnc-dbisqlconnection.hpp"
static QofLogModule log_module = G_LOG_DOMAIN;
+// gnc-dbiproviderimpl.hpp has templates that need log_module defined.
+#include "gnc-dbiproviderimpl.hpp"
static const unsigned int DBI_MAX_CONN_ATTEMPTS = 5;
constexpr const char *lock_table_name = "gnclock";
@@ -71,6 +73,21 @@ GncDbiSqlStatement::add_where_cond(QofIdTypeConst type_name,
}
}
+GncDbiSqlConnection::GncDbiSqlConnection (DbType type, QofBackend* qbe,
+ dbi_conn conn, bool ignore_lock) :
+ m_qbe{qbe}, m_conn{conn},
+ m_provider{std::move(type == DbType::DBI_SQLITE ?
+ make_dbi_provider<DbType::DBI_SQLITE>() :
+ type == DbType::DBI_MYSQL ?
+ make_dbi_provider<DbType::DBI_MYSQL>() :
+ make_dbi_provider<DbType::DBI_PGSQL>())},
+ m_conn_ok{true}, m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0},
+ m_retry{false}
+{
+ if (!lock_database(ignore_lock))
+ throw std::runtime_error("Failed to lock database!");
+}
+
bool
GncDbiSqlConnection::lock_database (bool ignore_lock)
{
diff --git a/src/backend/dbi/gnc-dbisqlconnection.hpp b/src/backend/dbi/gnc-dbisqlconnection.hpp
index 2118fe2..b97520f 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.hpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.hpp
@@ -35,14 +35,8 @@ class GncDbiProvider;
class GncDbiSqlConnection : public GncSqlConnection
{
public:
- GncDbiSqlConnection (std::unique_ptr<GncDbiProvider> provider,
- QofBackend* qbe, dbi_conn conn, bool ignore_lock) :
- m_qbe{qbe}, m_conn{conn}, m_provider{std::move(provider)},
- m_conn_ok{true}, m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0},
- m_retry{false} {
- if (!lock_database(ignore_lock))
- throw std::runtime_error("Failed to lock database!");
- }
+ GncDbiSqlConnection (DbType type, QofBackend* qbe, dbi_conn conn,
+ bool ignore_lock);
~GncDbiSqlConnection() override;
GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
noexcept override;
commit 5d38c7a7291cef83246bc0652d3e78fa44b995b5
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Jul 29 10:44:46 2016 -0700
Make conn_setup and the error handler functions templates on DbType.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 1e2ad4d..afff942 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -284,29 +284,34 @@ set_standard_connection_options (QofBackend* qbe, dbi_conn conn,
return true;
}
-static dbi_conn
-conn_setup (const char* dbtype, QofBackend* qbe,
- dbi_conn_error_handler_func err_handler, PairVec& options,
- UriStrings& uri)
+
+template <DbType Type> void error_handler(void* conn, void* data);
+void error_handler(void* conn, void* data);
+
+template <DbType Type>dbi_conn
+conn_setup (QofBackend* qbe, PairVec& options,
+ UriStrings& uri)
{
+ const char* dbstr = (Type == DbType::DBI_SQLITE ? "sqlite3" :
+ Type == DbType::DBI_MYSQL ? "mysql" : "pgsql");
#if HAVE_LIBDBI_R
dbi_conn conn;
if (dbi_instance)
- conn = dbi_conn_new_r (dbtype, dbi_instance);
+ conn = dbi_conn_new_r (dbstr, dbi_instance);
else
PERR ("Attempt to connect with an uninitialized dbi_instance");
#else
- auto conn = dbi_conn_new (dbtype);
+ auto conn = dbi_conn_new (dbstr);
#endif
if (conn == nullptr)
{
- PERR ("Unable to create %s dbi connection", dbtype);
+ PERR ("Unable to create %s dbi connection", dbstr);
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
return nullptr;
}
- dbi_conn_error_handler (conn, err_handler, qbe);
+ dbi_conn_error_handler (conn, error_handler<Type>, qbe);
if (!uri.m_dbname.empty() &&
!set_standard_connection_options(qbe, conn, uri))
@@ -384,8 +389,8 @@ create_database(DbType type, QofBackend *qbe, dbi_conn conn, const char* db)
return true;
}
-void
-sqlite3_error_fn (dbi_conn conn, void* user_data)
+template <> void
+error_handler<DbType::DBI_SQLITE> (dbi_conn conn, void* user_data)
{
const gchar* msg;
GncDbiBackend *be = static_cast<decltype(be)>(user_data);
@@ -447,7 +452,7 @@ gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session,
if (basename != nullptr) g_free (basename);
if (dirname != nullptr) g_free (dirname);
UriStrings uri;
- auto conn = conn_setup ("sqlite3", qbe, sqlite3_error_fn, options, uri);
+ auto conn = conn_setup<DbType::DBI_SQLITE>(qbe, options, uri);
if (conn == nullptr)
{
LEAVE("Error");
@@ -499,8 +504,8 @@ gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session,
}
-static void
-mysql_error_fn (dbi_conn conn, void* user_data)
+template <> void
+error_handler<DbType::DBI_MYSQL> (dbi_conn conn, void* user_data)
{
GncDbiBackend* be = (GncDbiBackend*)user_data;
const char* msg;
@@ -637,7 +642,7 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
be->connect(nullptr);
- auto conn = conn_setup("mysql", qbe, mysql_error_fn, options, uri);
+ auto conn = conn_setup<DbType::DBI_MYSQL>(qbe, options, uri);
if (conn == nullptr)
{
LEAVE("Error");
@@ -681,7 +686,7 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
LEAVE("Error");
return;
}
- conn = conn_setup("mysql", qbe, mysql_error_fn, options, uri);
+ conn = conn_setup<DbType::DBI_MYSQL>(qbe, options, uri);
result = dbi_conn_connect (conn);
if (result < 0)
{
@@ -724,8 +729,8 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
LEAVE (" ");
}
-static void
-pgsql_error_fn (dbi_conn conn, void* user_data)
+template<> void
+error_handler<DbType::DBI_PGSQL> (dbi_conn conn, void* user_data)
{
GncDbiBackend* be = (GncDbiBackend*)user_data;
const gchar* msg;
@@ -799,7 +804,7 @@ gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
g_free(lcname);
be->connect(nullptr);
- auto conn = conn_setup("pgsql", qbe, pgsql_error_fn, options, uri);
+ auto conn = conn_setup<DbType::DBI_PGSQL>(qbe, options, uri);
if (conn == nullptr)
{
LEAVE("Error");
@@ -842,7 +847,7 @@ gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
LEAVE("Error");
return;
}
- conn = conn_setup("pgsql", qbe, pgsql_error_fn, options, uri);
+ conn = conn_setup<DbType::DBI_PGSQL>(qbe, options, uri);
result = dbi_conn_connect (conn);
if (result < 0)
{
commit 314a5e10c2380bc29398d91afd3fdfcc2ae28146
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Jul 28 15:45:38 2016 -0700
Make gnc_lock_database a GncDbiSqlConnection member function.
Called from the constructor, so effective RAII with unlock_database called
from the destructor.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 1d1ee04..1e2ad4d 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -101,8 +101,6 @@ static QofLogModule log_module = G_LOG_DOMAIN;
// gnc-dbiproviderimpl.hpp has templates that need log_module defined.
#include "gnc-dbiproviderimpl.hpp"
-static gchar lock_table[] = "gnclock";
-
#define FILE_URI_TYPE "file"
#define FILE_URI_PREFIX (FILE_URI_TYPE "://")
#define SQLITE3_URI_TYPE "sqlite3"
@@ -114,7 +112,6 @@ constexpr const char* MYSQL_TIMESPEC_STR_FORMAT = "%04d%02d%02d%02d%02d%02d";
constexpr const char* PGSQL_TIMESPEC_STR_FORMAT = "%04d%02d%02d %02d%02d%02d";
static void adjust_sql_options (dbi_conn connection);
-static gboolean gnc_dbi_lock_database (QofBackend*, dbi_conn, gboolean);
static bool save_may_clobber_data (dbi_conn conn);
static void init_sql_backend (GncDbiBackend* dbi_be);
@@ -480,19 +477,18 @@ gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session,
g_unlink (filepath.c_str());
}
LEAVE("Bad DBI Library");
- return;
- }
- if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
- {
- qof_backend_set_error (qbe, ERR_BACKEND_LOCKED);
- LEAVE("Locked");
- return;
}
be->connect(nullptr);
- be->connect(
- new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_SQLITE>,
- qbe, conn, lock_table));
+ try
+ {
+ be->connect(new GncDbiSqlConnection(make_dbi_provider<DbType::DBI_SQLITE>(),
+ qbe, conn, ignore_lock));
+ }
+ catch (std::runtime_error& err)
+ {
+ return;
+ }
/* We should now have a proper session set up.
* Let's start logging */
@@ -555,136 +551,6 @@ mysql_error_fn (dbi_conn conn, void* user_data)
}
}
-
-/* FIXME: Move to GncDbiSqlConnection. */
-static gboolean
-gnc_dbi_lock_database (QofBackend* qbe, dbi_conn conn, gboolean ignore_lock)
-{
-
- GncDbiBackend* qe = (GncDbiBackend*)qbe;
-
- dbi_result result;
- const gchar* dbname = dbi_conn_get_option (conn, "dbname");
- /* Create the table if it doesn't exist */
- result = dbi_conn_get_table_list (conn, dbname, lock_table);
- if (! (result && dbi_result_get_numrows (result)))
- {
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- result = dbi_conn_queryf (conn,
- "CREATE TABLE %s ( Hostname varchar(%d), PID int )", lock_table,
- GNC_HOST_NAME_MAX);
- if (dbi_conn_error (conn, nullptr))
- {
- const gchar* errstr;
- dbi_conn_error (conn, &errstr);
- PERR ("Error %s creating lock table", errstr);
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- return FALSE;
- }
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- }
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
-
- /* Protect everything with a single transaction to prevent races */
- if ((result = dbi_conn_query (conn, "BEGIN")))
- {
- /* Check for an existing entry; delete it if ignore_lock is true, otherwise fail */
- gchar hostname[ GNC_HOST_NAME_MAX + 1 ];
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- result = dbi_conn_queryf (conn, "SELECT * FROM %s", lock_table);
- if (result && dbi_result_get_numrows (result))
- {
- dbi_result_free (result);
- result = nullptr;
- if (!ignore_lock)
- {
- qof_backend_set_error (qbe, ERR_BACKEND_LOCKED);
- /* FIXME: After enhancing the qof_backend_error mechanism, report in the dialog what is the hostname of the machine holding the lock. */
- dbi_conn_query (conn, "ROLLBACK");
- return FALSE;
- }
- result = dbi_conn_queryf (conn, "DELETE FROM %s", lock_table);
- if (!result)
- {
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- qof_backend_set_message (qbe, "Failed to delete lock record");
- result = dbi_conn_query (conn, "ROLLBACK");
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- return FALSE;
- }
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- }
- /* Add an entry and commit the transaction */
- memset (hostname, 0, sizeof (hostname));
- gethostname (hostname, GNC_HOST_NAME_MAX);
- result = dbi_conn_queryf (conn,
- "INSERT INTO %s VALUES ('%s', '%d')",
- lock_table, hostname, (int)GETPID ());
- if (!result)
- {
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- qof_backend_set_message (qbe, "Failed to create lock record");
- result = dbi_conn_query (conn, "ROLLBACK");
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- return FALSE;
- }
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- result = dbi_conn_query (conn, "COMMIT");
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- return TRUE;
- }
- /* Couldn't get a transaction (probably couldn't get a lock), so fail */
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- qof_backend_set_message (qbe, "SQL Backend failed to obtain a transaction");
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- return FALSE;
-}
-
#define SQL_OPTION_TO_REMOVE "NO_ZERO_DATE"
/* Given an sql_options string returns a copy of the string adjusted as
@@ -796,8 +662,6 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
return;
}
- if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
- return;
}
else
{
@@ -832,8 +696,6 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
return;
}
- if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
- return;
}
else
{
@@ -843,10 +705,15 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
}
be->connect(nullptr);
- be->connect(
- new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
- qbe, conn, lock_table));
-
+ try
+ {
+ be->connect(new GncDbiSqlConnection(make_dbi_provider<DbType::DBI_MYSQL>(),
+ qbe, conn, ignore_lock));
+ }
+ catch (std::runtime_error& err)
+ {
+ return;
+ }
/* We should now have a proper session set up.
* Let's start logging */
auto translog_path = gnc_build_translog_path (uri.basename().c_str());
@@ -956,8 +823,6 @@ gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
return;
}
- if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
- return;
}
else
{
@@ -993,8 +858,6 @@ gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
LEAVE("Error");
return;
}
- if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
- return;
}
else
{
@@ -1003,9 +866,15 @@ gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
}
}
be->connect(nullptr);
- be->connect(
- new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_PGSQL>,
- qbe, conn, lock_table));
+ try
+ {
+ be->connect(new GncDbiSqlConnection(make_dbi_provider<DbType::DBI_PGSQL>(),
+ qbe, conn, ignore_lock));
+ }
+ catch (std::runtime_error& err)
+ {
+ return;
+ }
/* We should now have a proper session set up.
* Let's start logging */
diff --git a/src/backend/dbi/gnc-dbiprovider.hpp b/src/backend/dbi/gnc-dbiprovider.hpp
index 453b911..e0a2561 100644
--- a/src/backend/dbi/gnc-dbiprovider.hpp
+++ b/src/backend/dbi/gnc-dbiprovider.hpp
@@ -49,4 +49,6 @@ public:
virtual void drop_index(dbi_conn conn, const std::string& index) = 0;
};
+using GncDbiProviderPtr = std::unique_ptr<GncDbiProvider>;
+
#endif //__GNC_DBIPROVIDER_HPP__
diff --git a/src/backend/dbi/gnc-dbiproviderimpl.hpp b/src/backend/dbi/gnc-dbiproviderimpl.hpp
index f991be6..a96461b 100644
--- a/src/backend/dbi/gnc-dbiproviderimpl.hpp
+++ b/src/backend/dbi/gnc-dbiproviderimpl.hpp
@@ -30,7 +30,6 @@ extern "C"
#include "gnc-backend-dbi.hpp"
#include "gnc-dbiprovider.hpp"
-
template <DbType T>
class GncDbiProviderImpl : public GncDbiProvider
{
@@ -41,6 +40,12 @@ public:
void drop_index(dbi_conn conn, const std::string& index);
};
+template <DbType T> GncDbiProviderPtr
+make_dbi_provider()
+{
+ return GncDbiProviderPtr(new GncDbiProviderImpl<T>);
+}
+
template<> void
GncDbiProviderImpl<DbType::DBI_SQLITE>::append_col_def(std::string& ddl,
const GncSqlColumnInfo& info)
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index 454e72c..98b9617 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -33,6 +33,7 @@ extern "C"
static QofLogModule log_module = G_LOG_DOMAIN;
static const unsigned int DBI_MAX_CONN_ATTEMPTS = 5;
+constexpr const char *lock_table_name = "gnclock";
/* --------------------------------------------------------- */
class GncDbiSqlStatement : public GncSqlStatement
@@ -70,6 +71,108 @@ GncDbiSqlStatement::add_where_cond(QofIdTypeConst type_name,
}
}
+bool
+GncDbiSqlConnection::lock_database (bool ignore_lock)
+{
+
+ auto dbname = dbi_conn_get_option (m_conn, "dbname");
+ /* Create the table if it doesn't exist */
+ auto result = dbi_conn_get_table_list (m_conn, dbname, lock_table_name);
+ int numrows = 0;
+ const char* errstr;
+ if (result) {
+ numrows = dbi_result_get_numrows (result);
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ if (numrows == 0)
+ {
+ result = dbi_conn_queryf (m_conn,
+ "CREATE TABLE %s ( Hostname varchar(%d), PID int )", lock_table_name,
+ GNC_HOST_NAME_MAX);
+ if (result)
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ if (dbi_conn_error (m_conn, &errstr))
+ {
+ PERR ("Error %s creating lock table", errstr);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ return false;
+ }
+ }
+
+ /* Protect everything with a single transaction to prevent races */
+ result = dbi_conn_query (m_conn, "BEGIN");
+ if (dbi_conn_error (m_conn, &errstr))
+ {
+ /* Couldn't get a transaction (probably couldn't get a lock), so fail */
+ std::string err{"SQL Backend failed to obtain a transaction: "};
+ err += errstr;
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_message (m_qbe, err.c_str());
+ return false;
+ }
+ dbi_result_free(result);
+ result = nullptr;
+ /* Check for an existing entry; delete it if ignore_lock is true, otherwise fail */
+ char hostname[ GNC_HOST_NAME_MAX + 1 ];
+ result = dbi_conn_queryf (m_conn, "SELECT * FROM %s", lock_table_name);
+ if (result && dbi_result_get_numrows (result))
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ if (!ignore_lock)
+ {
+ qof_backend_set_error (m_qbe, ERR_BACKEND_LOCKED);
+ /* FIXME: After enhancing the qof_backend_error mechanism, report in the dialog what is the hostname of the machine holding the lock. */
+ dbi_conn_query (m_conn, "ROLLBACK");
+ return false;
+ }
+ result = dbi_conn_queryf (m_conn, "DELETE FROM %s", lock_table_name);
+ if (!result)
+ {
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_message (m_qbe, "Failed to delete lock record");
+ result = dbi_conn_query (m_conn, "ROLLBACK");
+ if (result)
+ dbi_result_free (result);
+ return false;
+ }
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ /* Add an entry and commit the transaction */
+ memset (hostname, 0, sizeof (hostname));
+ gethostname (hostname, GNC_HOST_NAME_MAX);
+ result = dbi_conn_queryf (m_conn,
+ "INSERT INTO %s VALUES ('%s', '%d')",
+ lock_table_name, hostname, (int)GETPID ());
+ if (!result)
+ {
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_message (m_qbe, "Failed to create lock record");
+ result = dbi_conn_query (m_conn, "ROLLBACK");
+ if (result)
+ dbi_result_free (result);
+ return false;
+ }
+ dbi_result_free (result);
+ result = dbi_conn_query (m_conn, "COMMIT");
+ if (!result)
+ {
+ auto errnum = dbi_conn_error(m_conn, &errstr);
+ qof_backend_set_error(m_qbe, ERR_BACKEND_SERVER_ERR);
+ std::string err{"Failed to commit transaction: "};
+ err += errstr;
+ qof_backend_set_message(m_qbe, err.c_str());
+ return false;
+ }
+ dbi_result_free (result);
+ return true;
+}
+
void
GncDbiSqlConnection::unlock_database ()
{
@@ -81,7 +184,7 @@ GncDbiSqlConnection::unlock_database ()
auto dbname = dbi_conn_get_option (m_conn, "dbname");
/* Check if the lock table exists */
g_return_if_fail (dbname != nullptr);
- auto result = dbi_conn_get_table_list (m_conn, dbname, m_lock_table);
+ auto result = dbi_conn_get_table_list (m_conn, dbname, lock_table_name);
if (! (result && dbi_result_get_numrows (result)))
{
if (result)
@@ -105,7 +208,7 @@ GncDbiSqlConnection::unlock_database ()
memset (hostname, 0, sizeof (hostname));
gethostname (hostname, GNC_HOST_NAME_MAX);
result = dbi_conn_queryf (m_conn,
- "SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", m_lock_table, hostname,
+ "SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", lock_table_name, hostname,
(int)GETPID ());
if (result && dbi_result_get_numrows (result))
{
@@ -114,7 +217,7 @@ GncDbiSqlConnection::unlock_database ()
dbi_result_free (result);
result = nullptr;
}
- result = dbi_conn_queryf (m_conn, "DELETE FROM %s", m_lock_table);
+ result = dbi_conn_queryf (m_conn, "DELETE FROM %s", lock_table_name);
if (!result)
{
PERR ("Failed to delete the lock entry");
@@ -166,7 +269,6 @@ GncDbiSqlConnection::~GncDbiSqlConnection()
dbi_conn_close(m_conn);
m_conn = nullptr;
}
- delete m_provider;
}
GncSqlResultPtr
@@ -542,7 +644,7 @@ GncDbiSqlConnection::table_operation(const StrVec& table_names,
TableOpType op) noexcept
{
const char* dbname = dbi_conn_get_option (m_conn, "dbname");
- std::string lock_table{m_lock_table};
+ std::string lock_table{lock_table_name};
g_return_val_if_fail (!table_names.empty(), FALSE);
bool retval{true};
for (auto table : table_names)
diff --git a/src/backend/dbi/gnc-dbisqlconnection.hpp b/src/backend/dbi/gnc-dbisqlconnection.hpp
index 87e9b34..2118fe2 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.hpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.hpp
@@ -35,11 +35,14 @@ class GncDbiProvider;
class GncDbiSqlConnection : public GncSqlConnection
{
public:
- GncDbiSqlConnection (GncDbiProvider* provider, QofBackend* qbe,
- dbi_conn conn, const char* lock_table) :
- m_qbe{qbe}, m_conn{conn}, m_provider{provider}, m_conn_ok{true},
- m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0}, m_retry{false},
- m_lock_table{lock_table} {}
+ GncDbiSqlConnection (std::unique_ptr<GncDbiProvider> provider,
+ QofBackend* qbe, dbi_conn conn, bool ignore_lock) :
+ m_qbe{qbe}, m_conn{conn}, m_provider{std::move(provider)},
+ m_conn_ok{true}, m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0},
+ m_retry{false} {
+ if (!lock_database(ignore_lock))
+ throw std::runtime_error("Failed to lock database!");
+ }
~GncDbiSqlConnection() override;
GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
noexcept override;
@@ -61,7 +64,6 @@ public:
return dbi_conn_error(m_conn, nullptr); }
QofBackend* qbe () const noexcept { return m_qbe; }
dbi_conn conn() const noexcept { return m_conn; }
- GncDbiProvider* provider() { return m_provider; }
inline void set_error(int error, int repeat, bool retry) noexcept override
{
m_last_error = error;
@@ -87,7 +89,7 @@ public:
private:
QofBackend* m_qbe;
dbi_conn m_conn;
- GncDbiProvider* m_provider;
+ std::unique_ptr<GncDbiProvider> m_provider;
/** Used by the error handler routines to flag if the connection is ok to
* use
*/
@@ -106,7 +108,7 @@ private:
* original query)
*/
gboolean m_retry;
- const char* m_lock_table;
+ bool lock_database(bool ignore_lock);
void unlock_database();
};
commit 00e0a6e8b62cab8be1c2a4503fcecd056c28ee63
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Jul 28 09:18:25 2016 -0700
Change parameter of save_may_clobber_data from QofBackend to dbi_conn.
It actually needs the dbi_conn and that's known to its caller. Plus,
the backend's conn parameter hasn't actually been set so it was somewhat
coincidental that it worked.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 1f87d80..1d1ee04 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -115,7 +115,7 @@ constexpr const char* PGSQL_TIMESPEC_STR_FORMAT = "%04d%02d%02d %02d%02d%02d";
static void adjust_sql_options (dbi_conn connection);
static gboolean gnc_dbi_lock_database (QofBackend*, dbi_conn, gboolean);
-static gboolean save_may_clobber_data (QofBackend* qbe);
+static bool save_may_clobber_data (dbi_conn conn);
static void init_sql_backend (GncDbiBackend* dbi_be);
static bool conn_test_dbi_library (dbi_conn conn, QofBackend* qbe);
@@ -788,7 +788,7 @@ gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
LEAVE("Error");
return;
}
- if (create && !force && save_may_clobber_data (qbe))
+ if (create && !force && save_may_clobber_data (conn))
{
qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
PWARN ("Databse already exists, Might clobber it.");
@@ -948,7 +948,7 @@ gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
LEAVE("Error");
return;
}
- if (create && !force && save_may_clobber_data (qbe))
+ if (create && !force && save_may_clobber_data(conn))
{
qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
PWARN ("Databse already exists, Might clobber it.");
@@ -1106,17 +1106,14 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
/* ================================================================= */
-static gboolean
-save_may_clobber_data (QofBackend* qbe)
+static bool
+save_may_clobber_data (dbi_conn conn)
{
- GncDbiBackend* be = (GncDbiBackend*)qbe;
- const gchar* dbname;
- dbi_result result;
- gboolean retval = FALSE;
/* Data may be clobbered iff the number of tables != 0 */
- dbname = dbi_conn_get_option (be->conn(), "dbname");
- result = dbi_conn_get_table_list (be->conn(), dbname, nullptr);
+ auto dbname = dbi_conn_get_option (conn, "dbname");
+ auto result = dbi_conn_get_table_list (conn, dbname, nullptr);
+ bool retval = false;
if (result)
{
retval = dbi_result_get_numrows (result) > 0;
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index b3e3046..cf1b1ab 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -97,8 +97,6 @@ public:
{
m_conn->retry_connection(msg);
}
- /* Worst of all: */
- GncSqlConnection* conn() { return m_conn; }
/*-----*/
bool exists() { return m_exists; }
void set_exists(bool exists) { m_exists = exists; }
commit fc47b63265f33794720c5988e65da798000c35a5
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 26 17:40:29 2016 -0700
Templatize the session_begin functions and new_backend().
Thus removing the need for specializations of
QofDbiBackendProvider::create_backend().
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index f4216d9..1f87d80 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -109,16 +109,51 @@ static gchar lock_table[] = "gnclock";
#define SQLITE3_URI_PREFIX (SQLITE3_URI_TYPE "://")
#define PGSQL_DEFAULT_PORT 5432
-#define SQLITE3_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
-#define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
-#define PGSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d %02d%02d%02d"
+constexpr const char* SQLITE3_TIMESPEC_STR_FORMAT = "%04d%02d%02d%02d%02d%02d";
+constexpr const char* MYSQL_TIMESPEC_STR_FORMAT = "%04d%02d%02d%02d%02d%02d";
+constexpr const char* PGSQL_TIMESPEC_STR_FORMAT = "%04d%02d%02d %02d%02d%02d";
static void adjust_sql_options (dbi_conn connection);
static gboolean gnc_dbi_lock_database (QofBackend*, dbi_conn, gboolean);
static gboolean save_may_clobber_data (QofBackend* qbe);
+static void init_sql_backend (GncDbiBackend* dbi_be);
static bool conn_test_dbi_library (dbi_conn conn, QofBackend* qbe);
+template <DbType T> void gnc_dbi_session_begin(QofBackend* qbe,
+ QofSession* session,
+ const gchar* book_id,
+ gboolean ignore_lock,
+ gboolean create, gboolean force);
+template <DbType Type> QofBackend*
+new_backend ()
+{
+ QofBackend* be;
+ const char* format;
+ switch (Type)
+ {
+ case (DbType::DBI_SQLITE):
+ format = SQLITE3_TIMESPEC_STR_FORMAT;
+ break;
+ case (DbType::DBI_MYSQL):
+ format = MYSQL_TIMESPEC_STR_FORMAT;
+ break;
+ case (DbType::DBI_PGSQL):
+ format = PGSQL_TIMESPEC_STR_FORMAT;
+ break;
+ }
+ auto dbi_be = new GncDbiBackend(nullptr, nullptr, format);
+ g_assert (dbi_be != nullptr);
+
+ be = (QofBackend*)dbi_be;
+ qof_backend_init (be);
+
+ be->session_begin = gnc_dbi_session_begin<Type>;
+ init_sql_backend (dbi_be);
+
+ return be;
+}
+
template <DbType T>
class QofDbiBackendProvider : public QofBackendProvider
{
@@ -130,7 +165,7 @@ public:
QofDbiBackendProvider(QofDbiBackendProvider&&) = delete;
QofDbiBackendProvider operator=(QofDbiBackendProvider&&) = delete;
~QofDbiBackendProvider () = default;
- QofBackend* create_backend(void);
+ QofBackend* create_backend(void) { return new_backend<T>(); }
bool type_check(const char* type) { return true; }
};
@@ -363,8 +398,8 @@ sqlite3_error_fn (dbi_conn conn, void* user_data)
be->set_error (ERR_BACKEND_MISC, 0, false);
}
-void
-gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
+template <> void
+gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session,
const gchar* book_id, gboolean ignore_lock,
gboolean create, gboolean force)
{
@@ -714,8 +749,8 @@ adjust_sql_options (dbi_conn connection)
}
-static void
-gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
+template <> void
+gnc_dbi_session_begin<DbType::DBI_MYSQL> (QofBackend* qbe, QofSession* session,
const gchar* book_id, gboolean ignore_lock,
gboolean create, gboolean force)
{
@@ -867,8 +902,8 @@ pgsql_error_fn (dbi_conn conn, void* user_data)
}
}
-static void
-gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
+template <>void
+gnc_dbi_session_begin<DbType::DBI_PGSQL> (QofBackend* qbe, QofSession* session,
const gchar* book_id, gboolean ignore_lock,
gboolean create, gboolean force)
{
@@ -1207,47 +1242,6 @@ init_sql_backend (GncDbiBackend* dbi_be)
gnc_sql_init (dbi_be);
}
-static QofBackend*
-new_backend (void (*session_begin) (QofBackend*, QofSession*, const gchar*,
- gboolean, gboolean, gboolean),
- const char* format)
-{
- QofBackend* be;
-
- auto dbi_be = new GncDbiBackend(nullptr, nullptr, format);
- g_assert (dbi_be != nullptr);
-
- be = (QofBackend*)dbi_be;
- qof_backend_init (be);
-
- be->session_begin = session_begin;
- init_sql_backend (dbi_be);
-
- return be;
-}
-
-template<> QofBackend*
-QofDbiBackendProvider<DbType::DBI_SQLITE>::create_backend()
-{
- return new_backend (gnc_dbi_sqlite3_session_begin,
- SQLITE3_TIMESPEC_STR_FORMAT);
-}
-
-template<> QofBackend*
-QofDbiBackendProvider<DbType::DBI_MYSQL>::create_backend()
-{
- return new_backend (gnc_dbi_mysql_session_begin,
- MYSQL_TIMESPEC_STR_FORMAT);
-}
-
-template<> QofBackend*
-QofDbiBackendProvider<DbType::DBI_PGSQL>::create_backend()
-{
- return new_backend (gnc_dbi_postgres_session_begin,
- PGSQL_TIMESPEC_STR_FORMAT);
-}
-
-
/*
* Checks to see whether the file is an sqlite file or not
*1980
commit 61beed5686d840405325a278d2835e72fe927230
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 26 17:38:11 2016 -0700
Make sure that all of the GncDbiProviderImpl functions are in the right file.
Also merge create_table_ddl back into the only function that used it.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index eb518d0..f4216d9 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -467,34 +467,6 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
LEAVE ("");
}
-template<> StrVec
-GncDbiProviderImpl<DbType::DBI_SQLITE>::get_index_list (dbi_conn conn)
-{
- StrVec retval;
- const char* errmsg;
- dbi_result result = dbi_conn_query (conn,
- "SELECT name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_autoindex%'");
- if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
- {
- PWARN ("Index Table Retrieval Error: %s\n", errmsg);
- return retval;
- }
- while (dbi_result_next_row (result) != 0)
- {
- std::string index_name {dbi_result_get_string_idx (result, 1)};
- retval.push_back(index_name);
- }
- dbi_result_free (result);
- return retval;
-}
-
-template <DbType P> void
-GncDbiProviderImpl<P>::drop_index(dbi_conn conn, const std::string& index)
-{
- dbi_result result = dbi_conn_queryf (conn, "DROP INDEX %s", index.c_str());
- if (result)
- dbi_result_free (result);
-}
static void
mysql_error_fn (dbi_conn conn, void* user_data)
@@ -850,60 +822,6 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
LEAVE (" ");
}
-template<> StrVec
-GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
-{
- StrVec retval;
- const char* errmsg;
- auto dbname = dbi_conn_get_option (conn, "dbname");
- auto table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
- if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
- {
- PWARN ("Table Retrieval Error: %s\n", errmsg);
- return retval;
- }
- while (dbi_result_next_row (table_list) != 0)
- {
- auto table_name = dbi_result_get_string_idx (table_list, 1);
- auto result = dbi_conn_queryf (conn,
- "SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
- table_name);
- if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
- {
- PWARN ("Index Table Retrieval Error: %s on table %s\n",
- errmsg, table_name);
- continue;
- }
-
- while (dbi_result_next_row (result) != 0)
- {
- std::string index_name {dbi_result_get_string_idx (result, 3)};
- retval.push_back(index_name + " " + table_name);
- }
- dbi_result_free (result);
- }
-
- return retval;
-}
-
-template<> void
-GncDbiProviderImpl<DbType::DBI_MYSQL>::drop_index (dbi_conn conn, const std::string& index)
-{
- auto sep = index.find(' ', 0);
- if (index.find(' ', sep + 1) != std::string::npos)
- {
- PWARN("Drop index error: invalid MySQL index format (<index> <table>): %s",
- index.c_str());
- return;
- }
-
- auto result = dbi_conn_queryf (conn, "DROP INDEX %s ON %s",
- index.substr(0, sep).c_str(),
- index.substr(sep + 1).c_str());
- if (result)
- dbi_result_free (result);
-}
-
static void
pgsql_error_fn (dbi_conn conn, void* user_data)
{
@@ -1064,27 +982,6 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
LEAVE (" ");
}
-template<> StrVec
-GncDbiProviderImpl<DbType::DBI_PGSQL>::get_index_list (dbi_conn conn)
-{
- StrVec retval;
- const char* errmsg;
- PINFO ("Retrieving postgres index list\n");
- auto result = dbi_conn_query (conn,
- "SELECT relname FROM pg_class AS a INNER JOIN pg_index AS b ON (b.indexrelid = a.oid) INNER JOIN pg_namespace AS c ON (a.relnamespace = c.oid) WHERE reltype = '0' AND indisprimary = 'f' AND nspname = 'public'");
- if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
- {
- PWARN("Index Table Retrieval Error: %s\n", errmsg);
- return retval;
- }
- while (dbi_result_next_row (result) != 0)
- {
- std::string index_name {dbi_result_get_string_idx (result, 1)};
- retval.push_back(index_name);
- }
- dbi_result_free (result);
- return retval;
-}
/* ================================================================= */
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index b959f51..b3e3046 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -68,6 +68,15 @@ typedef enum
GNC_DBI_FAIL_TEST
} GncDbiTestResult;
+/**
+ * Supported Dbi Backends.
+ */
+enum class DbType
+{
+ DBI_SQLITE, /**< Sqlite3 */
+ DBI_MYSQL, /**< MySQL and probably MariaDB */
+ DBI_PGSQL /**< Postgresql */
+};
/**
* Implementations of GncSqlBackend.
diff --git a/src/backend/dbi/gnc-dbiprovider.hpp b/src/backend/dbi/gnc-dbiprovider.hpp
index 21d749e..453b911 100644
--- a/src/backend/dbi/gnc-dbiprovider.hpp
+++ b/src/backend/dbi/gnc-dbiprovider.hpp
@@ -42,9 +42,6 @@ class GncDbiProvider
{
public:
virtual ~GncDbiProvider() = default;
- virtual std::string create_table_ddl(const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec) = 0;
virtual StrVec get_table_list(dbi_conn conn, const std::string& dbname) = 0;
virtual void append_col_def(std::string& ddl,
const GncSqlColumnInfo& info) = 0;
diff --git a/src/backend/dbi/gnc-dbiproviderimpl.hpp b/src/backend/dbi/gnc-dbiproviderimpl.hpp
index 2b9103a..f991be6 100644
--- a/src/backend/dbi/gnc-dbiproviderimpl.hpp
+++ b/src/backend/dbi/gnc-dbiproviderimpl.hpp
@@ -30,22 +30,12 @@ extern "C"
#include "gnc-backend-dbi.hpp"
#include "gnc-dbiprovider.hpp"
-enum class DbType
-{
- DBI_SQLITE,
- DBI_MYSQL,
- DBI_PGSQL
-};
template <DbType T>
class GncDbiProviderImpl : public GncDbiProvider
{
public:
- std::string create_table_ddl(const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec);
- StrVec get_table_list(dbi_conn conn,
- const std::string& dbname);
+ StrVec get_table_list(dbi_conn conn, const std::string& dbname);
void append_col_def(std::string& ddl, const GncSqlColumnInfo& info);
StrVec get_index_list (dbi_conn conn);
void drop_index(dbi_conn conn, const std::string& index);
@@ -98,28 +88,6 @@ GncDbiProviderImpl<DbType::DBI_SQLITE>::append_col_def(std::string& ddl,
}
}
-template <DbType P> std::string
-GncDbiProviderImpl<P>::create_table_ddl (const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec)
-{
- std::string ddl;
- unsigned int col_num = 0;
-
- g_return_val_if_fail (conn != nullptr, ddl);
- ddl += "CREATE TABLE " + table_name + "(";
- for (auto const& info : info_vec)
- {
- if (col_num++ != 0)
- {
- ddl += ", ";
- }
- append_col_def (ddl, info);
- }
- ddl += ")";
-
- return ddl;
-}
template<> void
GncDbiProviderImpl<DbType::DBI_MYSQL>::append_col_def (std::string& ddl,
@@ -290,4 +258,109 @@ GncDbiProviderImpl<DbType::DBI_PGSQL>::get_table_list (dbi_conn conn,
return list;
}
+template<> StrVec
+GncDbiProviderImpl<DbType::DBI_SQLITE>::get_index_list (dbi_conn conn)
+{
+ StrVec retval;
+ const char* errmsg;
+ dbi_result result = dbi_conn_query (conn,
+ "SELECT name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_autoindex%'");
+ if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
+ {
+ PWARN ("Index Table Retrieval Error: %s\n", errmsg);
+ return retval;
+ }
+ while (dbi_result_next_row (result) != 0)
+ {
+ std::string index_name {dbi_result_get_string_idx (result, 1)};
+ retval.push_back(index_name);
+ }
+ dbi_result_free (result);
+ return retval;
+}
+
+template<> StrVec
+GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
+{
+ StrVec retval;
+ const char* errmsg;
+ auto dbname = dbi_conn_get_option (conn, "dbname");
+ auto table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
+ if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
+ {
+ PWARN ("Table Retrieval Error: %s\n", errmsg);
+ return retval;
+ }
+ while (dbi_result_next_row (table_list) != 0)
+ {
+ auto table_name = dbi_result_get_string_idx (table_list, 1);
+ auto result = dbi_conn_queryf (conn,
+ "SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
+ table_name);
+ if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
+ {
+ PWARN ("Index Table Retrieval Error: %s on table %s\n",
+ errmsg, table_name);
+ continue;
+ }
+
+ while (dbi_result_next_row (result) != 0)
+ {
+ std::string index_name {dbi_result_get_string_idx (result, 3)};
+ retval.push_back(index_name + " " + table_name);
+ }
+ dbi_result_free (result);
+ }
+
+ return retval;
+}
+
+template<> StrVec
+GncDbiProviderImpl<DbType::DBI_PGSQL>::get_index_list (dbi_conn conn)
+{
+ StrVec retval;
+ const char* errmsg;
+ PINFO ("Retrieving postgres index list\n");
+ auto result = dbi_conn_query (conn,
+ "SELECT relname FROM pg_class AS a INNER JOIN pg_index AS b ON (b.indexrelid = a.oid) INNER JOIN pg_namespace AS c ON (a.relnamespace = c.oid) WHERE reltype = '0' AND indisprimary = 'f' AND nspname = 'public'");
+ if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
+ {
+ PWARN("Index Table Retrieval Error: %s\n", errmsg);
+ return retval;
+ }
+ while (dbi_result_next_row (result) != 0)
+ {
+ std::string index_name {dbi_result_get_string_idx (result, 1)};
+ retval.push_back(index_name);
+ }
+ dbi_result_free (result);
+ return retval;
+}
+
+template <DbType P> void
+GncDbiProviderImpl<P>::drop_index(dbi_conn conn, const std::string& index)
+{
+ dbi_result result = dbi_conn_queryf (conn, "DROP INDEX %s", index.c_str());
+ if (result)
+ dbi_result_free (result);
+}
+
+template<> void
+GncDbiProviderImpl<DbType::DBI_MYSQL>::drop_index (dbi_conn conn, const std::string& index)
+{
+
+ auto sep = index.find(' ', 0);
+ if (index.find(' ', sep + 1) != std::string::npos)
+ {
+ PWARN("Drop index error: invalid MySQL index format (<index> <table>): %s",
+ index.c_str());
+ return;
+ }
+
+ auto result = dbi_conn_queryf (conn, "DROP INDEX %s ON %s",
+ index.substr(0, sep).c_str(),
+ index.substr(sep + 1).c_str());
+ if (result)
+ dbi_result_free (result);
+}
#endif //__GNC_DBISQLPROVIDERIMPL_HPP__
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index c866cb5..454e72c 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -330,7 +330,20 @@ bool
GncDbiSqlConnection::create_table (const std::string& table_name,
const ColVec& info_vec) const noexcept
{
- auto ddl = m_provider->create_table_ddl(this, table_name, info_vec);
+ std::string ddl;
+ unsigned int col_num = 0;
+
+ ddl += "CREATE TABLE " + table_name + "(";
+ for (auto const& info : info_vec)
+ {
+ if (col_num++ != 0)
+ {
+ ddl += ", ";
+ }
+ m_provider->append_col_def (ddl, info);
+ }
+ ddl += ")";
+
if (ddl.empty())
return false;
diff --git a/src/backend/dbi/gnc-dbisqlconnection.hpp b/src/backend/dbi/gnc-dbisqlconnection.hpp
index 547ae2b..87e9b34 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.hpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.hpp
@@ -78,8 +78,6 @@ public:
bool verify() noexcept override;
bool retry_connection(const char* msg) noexcept override;
dbi_result table_manage_backup(const std::string& table_name, TableOpType op);
- /* FIXME: These three friend functions should really be members, but doing
- * that is too invasive just yet. */
bool table_operation (const StrVec& table_name_list,
TableOpType op) noexcept;
std::string add_columns_ddl(const std::string& table_name,
commit 31c73a141e94d8ff1ff1cf4a12d44defe70eb616
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 26 16:15:14 2016 -0700
Extract functions conn_setup and create_database.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 339baca..eb518d0 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -113,6 +113,7 @@ static gchar lock_table[] = "gnclock";
#define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
#define PGSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d %02d%02d%02d"
+static void adjust_sql_options (dbi_conn connection);
static gboolean gnc_dbi_lock_database (QofBackend*, dbi_conn, gboolean);
static gboolean save_may_clobber_data (QofBackend* qbe);
@@ -137,7 +138,9 @@ public:
/* ================================================================= */
struct UriStrings
{
+ UriStrings() = default;
UriStrings(const std::string& uri);
+ ~UriStrings() = default;
std::string basename() const noexcept;
const char* dbname() const noexcept;
std::string m_protocol;
@@ -209,6 +212,146 @@ set_options(dbi_conn conn, const PairVec& options)
}
}
+/**
+ * Sets standard db options in a dbi_conn.
+ *
+ * @param qbe QOF backend
+ * @param conn dbi_conn connection
+ * @param uri UriStrings containing the needed paramters.
+ * @return TRUE if successful, FALSE if error
+ */
+static bool
+set_standard_connection_options (QofBackend* qbe, dbi_conn conn,
+ const UriStrings& uri)
+
+{
+ gint result;
+ PairVec options;
+ options.push_back(std::make_pair("host", uri.m_host));
+ options.push_back(std::make_pair("dbname", uri.m_dbname));
+ options.push_back(std::make_pair("username", uri.m_username));
+ options.push_back(std::make_pair("password", uri.m_password));
+ options.push_back(std::make_pair("encoding", "UTF-8"));
+ try
+ {
+ set_options(conn, options);
+ auto result = dbi_conn_set_option_numeric(conn, "port", uri.m_portnum);
+ if (result < 0)
+ {
+ const char *msg = nullptr;
+ auto err = dbi_conn_error(conn, &msg);
+ PERR("Error setting port option to %d: %s", uri.m_portnum, msg);
+ throw std::runtime_error(msg);
+ }
+ }
+ catch (std::runtime_error& err)
+ {
+ qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
+ return false;
+ }
+
+ return true;
+}
+static dbi_conn
+conn_setup (const char* dbtype, QofBackend* qbe,
+ dbi_conn_error_handler_func err_handler, PairVec& options,
+ UriStrings& uri)
+{
+#if HAVE_LIBDBI_R
+ dbi_conn conn;
+ if (dbi_instance)
+ conn = dbi_conn_new_r (dbtype, dbi_instance);
+ else
+ PERR ("Attempt to connect with an uninitialized dbi_instance");
+#else
+ auto conn = dbi_conn_new (dbtype);
+#endif
+
+ if (conn == nullptr)
+ {
+ PERR ("Unable to create %s dbi connection", dbtype);
+ qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
+ return nullptr;
+ }
+
+ dbi_conn_error_handler (conn, err_handler, qbe);
+
+ if (!uri.m_dbname.empty() &&
+ !set_standard_connection_options(qbe, conn, uri))
+ {
+ dbi_conn_close(conn);
+ return nullptr;
+ }
+ if(!options.empty())
+ {
+ try {
+ set_options(conn, options);
+ }
+ catch (std::runtime_error& err)
+ {
+ dbi_conn_close(conn);
+ qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
+ return nullptr;
+ }
+ }
+
+ return conn;
+}
+
+static bool
+create_database(DbType type, QofBackend *qbe, dbi_conn conn, const char* db)
+{
+ const char *dbname;
+ const char *dbcreate;
+ if (type == DbType::DBI_MYSQL)
+ {
+ dbname = "mysql";
+ dbcreate = "CREATE DATABASE %s CHARACTER SET utf8";
+ }
+ else
+ {
+ dbname = "postgres";
+ dbcreate = "CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'";
+ }
+ PairVec options;
+ options.push_back(std::make_pair("dbname", dbname));
+ try
+ {
+ set_options(conn, options);
+ }
+ catch (std::runtime_error& err)
+ {
+ qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
+ return false;
+ }
+
+ auto result = dbi_conn_connect (conn);
+ if (result < 0)
+ {
+ PERR ("Unable to connect to %s database", dbname);
+ qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
+ return false;
+ }
+ if (type == DbType::DBI_MYSQL)
+ adjust_sql_options(conn);
+ auto dresult = dbi_conn_queryf (conn, dbcreate, db);
+ if (dresult == nullptr)
+ {
+ PERR ("Unable to create database '%s'\n", db);
+ qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
+ return false;
+ }
+ if (type == DbType::DBI_PGSQL)
+ {
+ const char *alterdb = "ALTER DATABASE %s SET "
+ "standard_conforming_strings TO on";
+ dbi_conn_queryf (conn, alterdb, db);
+ }
+ dbi_conn_close(conn);
+ conn = nullptr;
+ return true;
+}
+
void
sqlite3_error_fn (dbi_conn conn, void* user_data)
{
@@ -226,10 +369,8 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
gboolean create, gboolean force)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- gint result;
const char* msg = nullptr;
gboolean file_exists;
- GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
PairVec options;
g_return_if_fail (qbe != nullptr);
@@ -265,25 +406,6 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
}
be->connect(nullptr);
- dbi_conn conn;
-#if HAVE_LIBDBI_R
- if (dbi_instance)
- conn = dbi_conn_new_r ("sqlite3", dbi_instance);
- else
- PERR ("Attempt to connect with an uninitialized dbi_instance");
-#else
- conn = dbi_conn_new ("sqlite3");
-#endif
-
- if (conn == nullptr)
- {
- PERR ("Unable to create sqlite3 dbi connection\n");
- qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
- LEAVE("Error");
- return;
- }
-
- dbi_conn_error_handler (conn, sqlite3_error_fn, be);
/* dbi-sqlite3 documentation says that sqlite3 doesn't take a "host" option */
options.push_back(std::make_pair("host", "localhost"));
auto dirname = g_path_get_dirname (filepath.c_str());
@@ -292,20 +414,19 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
options.push_back(std::make_pair("sqlite3_dbdir", dirname));
if (basename != nullptr) g_free (basename);
if (dirname != nullptr) g_free (dirname);
-
- try {
- set_options(conn, options);
- }
- catch (std::runtime_error& err)
+ UriStrings uri;
+ auto conn = conn_setup ("sqlite3", qbe, sqlite3_error_fn, options, uri);
+ if (conn == nullptr)
{
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
LEAVE("Error");
- return;
+ return;
}
- result = dbi_conn_connect (conn);
+
+ auto result = dbi_conn_connect (conn);
if (result < 0)
{
+ dbi_conn_close(conn);
PERR ("Unable to connect to %s: %d\n", book_id, result);
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
LEAVE("Error");
@@ -314,22 +435,22 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
if (!conn_test_dbi_library(conn, qbe))
{
- if (create && !file_exists) /* File didn't exist before, but it */
+ if (create && !file_exists)
{
- /* does now, and we don't want to */
- dbi_conn_close (conn); /* leave it lying around. */
+ /* File didn't exist before, but it does now, and we don't want to
+ * leave it lying around.
+ */
+ dbi_conn_close (conn);
conn = nullptr;
g_unlink (filepath.c_str());
}
- msg = "Bad DBI Library";
- LEAVE("Error");
+ LEAVE("Bad DBI Library");
return;
}
if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
{
qof_backend_set_error (qbe, ERR_BACKEND_LOCKED);
- msg = "Locked";
- LEAVE("Error");
+ LEAVE("Locked");
return;
}
@@ -343,7 +464,7 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
xaccLogSetBaseName (filepath.c_str());
PINFO ("logpath=%s", filepath.c_str() ? filepath.c_str() : "(null)");
- LEAVE ("%s", msg);
+ LEAVE ("");
}
template<> StrVec
@@ -427,51 +548,6 @@ mysql_error_fn (dbi_conn conn, void* user_data)
}
}
-/**
- * Sets standard db options in a dbi_conn.
- *
- * @param qbe QOF backend
- * @param conn dbi_conn connection
- * @param host Hostname
- * @param port Port number
- * @param dbname Database name
- * @param username User name
- * @param password Password
- * @return TRUE if successful, FALSE if error
- */
-static bool
-set_standard_connection_options (QofBackend* qbe, dbi_conn conn,
- const UriStrings& uri)
-
-{
- gint result;
- PairVec options;
- options.push_back(std::make_pair("host", uri.m_host));
- options.push_back(std::make_pair("dbname", uri.m_dbname));
- options.push_back(std::make_pair("username", uri.m_username));
- options.push_back(std::make_pair("password", uri.m_password));
- options.push_back(std::make_pair("encoding", "UTF-8"));
- try
- {
- set_options(conn, options);
- auto result = dbi_conn_set_option_numeric(conn, "port", uri.m_portnum);
- if (result < 0)
- {
- const char *msg = nullptr;
- auto err = dbi_conn_error(conn, &msg);
- PERR("Error setting port option to %d: %s", uri.m_portnum, msg);
- throw std::runtime_error(msg);
- }
- }
- catch (std::runtime_error& err)
- {
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- return false;
- }
-
-
- return true;
-}
/* FIXME: Move to GncDbiSqlConnection. */
static gboolean
@@ -672,10 +748,6 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
gboolean create, gboolean force)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- gchar* basename = nullptr;
- gchar* translog_path = nullptr;
- gint result;
- gboolean success = FALSE;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
PairVec options;
@@ -690,34 +762,17 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
where username, password and port are optional) */
UriStrings uri(book_id);
- // Try to connect to the db. If it doesn't exist and the create
- // flag is TRUE, we'll need to connect to the 'mysql' db and execute the
- // CREATE DATABASE ddl statement there.
be->connect(nullptr);
- dbi_conn conn;
-#if HAVE_LIBDBI_R
- if (dbi_instance)
- conn = dbi_conn_new_r ("mysql", dbi_instance);
- else
- PERR ("Attempt to connect with an uninitialized dbi_instance");
-#else
- conn = dbi_conn_new ("mysql");
-#endif
+
+ auto conn = conn_setup("mysql", qbe, mysql_error_fn, options, uri);
if (conn == nullptr)
{
- PERR ("Unable to create mysql dbi connection\n");
- qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
LEAVE("Error");
return;
}
- dbi_conn_error_handler (conn, mysql_error_fn, be);
- if (!set_standard_connection_options (qbe, conn, uri))
- {
- LEAVE("Error");
- return;
- }
- be->set_exists(true);
- result = dbi_conn_connect (conn);
+
+ be->set_exists(true); //May be unset in the error handler.
+ auto result = dbi_conn_connect (conn);
if (result == 0)
{
adjust_sql_options (conn);
@@ -734,7 +789,8 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
return;
}
- success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
+ if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
+ return;
}
else
{
@@ -747,67 +803,14 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
return;
}
- // The db does not already exist. Connect to the 'mysql' db and try to create it.
if (create)
{
- options.push_back(std::make_pair("dbname", "mysql"));
- try
- {
- set_options(conn, options);
- }
- catch (std::runtime_error& err)
- {
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- LEAVE("Error");
- return;
- }
-
- result = dbi_conn_connect (conn);
- if (result < 0)
- {
- PERR ("Unable to connect to 'mysql' database\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- LEAVE("Error");
- return;
- }
- adjust_sql_options (conn);
- auto dresult = dbi_conn_queryf (conn,
- "CREATE DATABASE %s CHARACTER SET utf8",
- uri.dbname());
- if (dresult == nullptr)
- {
- PERR ("Unable to create database '%s'\n", uri.dbname());
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- LEAVE("Error");
- return;
- }
- dbi_conn_close (conn);
- conn = nullptr;
-
- // Try again to connect to the db
-#if HAVE_LIBDBI_R
- if (dbi_instance)
- conn = dbi_conn_new_r ("mysql", dbi_instance);
- else
- PERR ("Attempt to connect with an uninitialized dbi_instance");
-#else
- conn = dbi_conn_new ("mysql");
-#endif
-
- if (conn == nullptr)
+ if (!create_database(DbType::DBI_MYSQL, qbe, conn, uri.dbname()))
{
- PERR ("Unable to create mysql dbi connection\n");
- qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
LEAVE("Error");
return;
}
- dbi_conn_error_handler (conn, mysql_error_fn, be);
- uri.m_portnum = 0;
- if (!set_standard_connection_options (qbe, conn, uri))
- {
- LEAVE("Error: Failed to set options.");
- return;
- }
+ conn = conn_setup("mysql", qbe, mysql_error_fn, options, uri);
result = dbi_conn_connect (conn);
if (result < 0)
{
@@ -822,7 +825,8 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
return;
}
- success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
+ if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
+ return;
}
else
{
@@ -831,17 +835,14 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
}
}
- if (success)
- {
- be->connect(nullptr);
- be->connect(
- new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
- qbe, conn, lock_table));
- }
+ be->connect(nullptr);
+ be->connect(
+ new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
+ qbe, conn, lock_table));
/* We should now have a proper session set up.
* Let's start logging */
- translog_path = gnc_build_translog_path (uri.basename().c_str());
+ auto translog_path = gnc_build_translog_path (uri.basename().c_str());
xaccLogSetBaseName (translog_path);
PINFO ("logpath=%s", translog_path ? translog_path : "(null)");
g_free (translog_path);
@@ -954,9 +955,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
gboolean create, gboolean force)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- gint result = 0;
- gboolean success = FALSE;
- GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
+ bool success = false;
PairVec options;
g_return_if_fail (qbe != nullptr);
@@ -978,35 +977,17 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
auto lcname = g_utf8_strdown (uri.dbname(), -1);
uri.m_dbname = std::string{lcname};
g_free(lcname);
- // Try to connect to the db. If it doesn't exist and the create
- // flag is TRUE, we'll need to connect to the 'postgres' db and execute the
- // CREATE DATABASE ddl statement there.
be->connect(nullptr);
- dbi_conn conn;
-#if HAVE_LIBDBI_R
- if (dbi_instance)
- conn = dbi_conn_new_r ("pgsql", dbi_instance);
- else
- PERR ("Attempt to connect with an uninitialized dbi_instance");
-#else
- conn = dbi_conn_new ("pgsql");
-#endif
+ auto conn = conn_setup("pgsql", qbe, pgsql_error_fn, options, uri);
if (conn == nullptr)
{
- PERR ("Unable to create pgsql dbi connection\n");
- qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
LEAVE("Error");
- return;
- }
- dbi_conn_error_handler (conn, pgsql_error_fn, be);
- if (!set_standard_connection_options (qbe, conn, uri))
- {
- LEAVE("Error");
- return;
+ return;
}
- be->set_exists(true);
- result = dbi_conn_connect (conn);
+
+ be->set_exists(true); //May be unset in the error handler.
+ auto result = dbi_conn_connect (conn);
if (result == 0)
{
if (!conn_test_dbi_library(conn, qbe))
@@ -1022,7 +1003,8 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
return;
}
- success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
+ if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
+ return;
}
else
{
@@ -1035,66 +1017,14 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
return;
}
- // The db does not already exist. Connect to the 'postgres' db and try to create it.
if (create)
{
- options.push_back(std::make_pair("dbname", "postgres"));
- try
- {
- set_options(conn, options);
- }
- catch (std::runtime_error& err)
- {
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- LEAVE("Error");
- return;
- }
-
- result = dbi_conn_connect (conn);
- if (result < 0)
- {
- PERR ("Unable to connect to 'postgres' database\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- LEAVE("Error");
- return;
- }
- auto dresult = dbi_conn_queryf (conn,
- "CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'", uri.dbname());
- if (dresult == nullptr)
- {
- PERR ("Unable to create database '%s'\n", uri.dbname());
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- LEAVE("Error");
- return;
- }
- dbi_conn_queryf (conn,
- "ALTER DATABASE %s SET standard_conforming_strings TO on", uri.dbname());
- dbi_conn_close (conn);
-
- // Try again to connect to the db
-#if HAVE_LIBDBI_R
- if (dbi_instance)
- conn = dbi_conn_new_r ("pgsql", dbi_instance);
- else
- PERR ("Attempt to connect with an uninitialized dbi_instance");
-#else
- conn = dbi_conn_new ("pgsql");
-#endif
-
- if (conn == nullptr)
- {
- PERR ("Unable to create pgsql dbi connection\n");
- qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
- LEAVE("Error");
- return;
- }
- dbi_conn_error_handler (conn, pgsql_error_fn, be);
- uri.m_portnum = PGSQL_DEFAULT_PORT;
- if (!set_standard_connection_options (qbe, conn, uri))
+ if (!create_database(DbType::DBI_PGSQL, qbe, conn, uri.dbname()))
{
LEAVE("Error");
return;
}
+ conn = conn_setup("pgsql", qbe, pgsql_error_fn, options, uri);
result = dbi_conn_connect (conn);
if (result < 0)
{
@@ -1110,7 +1040,8 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
LEAVE("Error");
return;
}
- success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
+ if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
+ return;
}
else
{
@@ -1118,13 +1049,10 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
qof_backend_set_message (qbe, "Database %s not found", uri.dbname());
}
}
- if (success)
- {
- be->connect(nullptr);
- be->connect(
+ be->connect(nullptr);
+ be->connect(
new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_PGSQL>,
qbe, conn, lock_table));
- }
/* We should now have a proper session set up.
* Let's start logging */
commit 37d425733613aaf9c11272989d7d7305f9b075dd
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 26 13:54:45 2016 -0700
Extract-function conn_test_dbi_library.
Renaming the previous so-named function dbi_library_test.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index de41bd7..339baca 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -116,7 +116,7 @@ static gchar lock_table[] = "gnclock";
static gboolean gnc_dbi_lock_database (QofBackend*, dbi_conn, gboolean);
static gboolean save_may_clobber_data (QofBackend* qbe);
-static GncDbiTestResult conn_test_dbi_library (dbi_conn conn);
+static bool conn_test_dbi_library (dbi_conn conn, QofBackend* qbe);
template <DbType T>
class QofDbiBackendProvider : public QofBackendProvider
@@ -312,25 +312,7 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
return;
}
- dbi_test_result = conn_test_dbi_library (conn);
- switch (dbi_test_result)
- {
- case GNC_DBI_PASS:
- break;
-
- case GNC_DBI_FAIL_SETUP:
- qof_backend_set_error (qbe, ERR_SQL_DBI_UNTESTABLE);
- qof_backend_set_message (qbe,
- "SQLite3: Failed to setup for large number test");
- break;
-
- case GNC_DBI_FAIL_TEST:
- qof_backend_set_error (qbe, ERR_SQL_BAD_DBI);
- qof_backend_set_message (qbe,
- "SQLite3 DBI library fails large number test");
- break;
- }
- if (dbi_test_result != GNC_DBI_PASS)
+ if (!conn_test_dbi_library(conn, qbe))
{
if (create && !file_exists) /* File didn't exist before, but it */
{
@@ -739,25 +721,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
if (result == 0)
{
adjust_sql_options (conn);
- dbi_test_result = conn_test_dbi_library (conn);
- switch (dbi_test_result)
- {
- case GNC_DBI_PASS:
- break;
-
- case GNC_DBI_FAIL_SETUP:
- qof_backend_set_error (qbe, ERR_SQL_DBI_UNTESTABLE);
- qof_backend_set_message (qbe,
- "DBI library large number test incomplete");
- break;
-
- case GNC_DBI_FAIL_TEST:
- qof_backend_set_error (qbe, ERR_SQL_BAD_DBI);
- qof_backend_set_message (qbe,
- "DBI library fails large number test");
- break;
- }
- if (GNC_DBI_PASS != dbi_test_result)
+ if(!conn_test_dbi_library(conn, qbe))
{
LEAVE("Error");
return;
@@ -853,25 +817,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
return;
}
adjust_sql_options (conn);
- dbi_test_result = conn_test_dbi_library (conn);
- switch (dbi_test_result)
- {
- case GNC_DBI_PASS:
- break;
-
- case GNC_DBI_FAIL_SETUP:
- qof_backend_set_error (qbe, ERR_SQL_DBI_UNTESTABLE);
- qof_backend_set_message (qbe,
- "MySql: Failed to setup for large number test");
- break;
-
- case GNC_DBI_FAIL_TEST:
- qof_backend_set_error (qbe, ERR_SQL_BAD_DBI);
- qof_backend_set_message (qbe,
- "MySql DBI library fails large number test");
- break;
- }
- if (dbi_test_result != GNC_DBI_PASS)
+ if (!conn_test_dbi_library(conn, qbe))
{
dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
return;
@@ -1063,25 +1009,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
result = dbi_conn_connect (conn);
if (result == 0)
{
- dbi_test_result = conn_test_dbi_library (conn);
- switch (dbi_test_result)
- {
- case GNC_DBI_PASS:
- break;
-
- case GNC_DBI_FAIL_SETUP:
- qof_backend_set_error (qbe, ERR_SQL_DBI_UNTESTABLE);
- qof_backend_set_message (qbe,
- "Postgresql: Failed to setup for large number test");
- break;
-
- case GNC_DBI_FAIL_TEST:
- qof_backend_set_error (qbe, ERR_SQL_BAD_DBI);
- qof_backend_set_message (qbe,
- "Postgresql DBI library fails large number test");
- break;
- }
- if (dbi_test_result != GNC_DBI_PASS)
+ if (!conn_test_dbi_library(conn, qbe))
{
LEAVE("Error");
return;
@@ -1175,25 +1103,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
LEAVE("Error");
return;
}
- dbi_test_result = conn_test_dbi_library (conn);
- switch (dbi_test_result)
- {
- case GNC_DBI_PASS:
- break;
-
- case GNC_DBI_FAIL_SETUP:
- qof_backend_set_error (qbe, ERR_SQL_DBI_UNTESTABLE);
- qof_backend_set_message (qbe,
- "DBI library large number test incomplete");
- break;
-
- case GNC_DBI_FAIL_TEST:
- qof_backend_set_error (qbe, ERR_SQL_BAD_DBI);
- qof_backend_set_message (qbe,
- "DBI library fails large number test");
- break;
- }
- if (GNC_DBI_PASS != dbi_test_result)
+ if (!conn_test_dbi_library(conn, qbe))
{
dbi_conn_select_db (conn, "template1");
dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
@@ -1702,7 +1612,7 @@ gnc_module_finalize_backend_dbi (void)
* GNC_DBI_FAIL_TEST if the bug was found.
*/
static GncDbiTestResult
-conn_test_dbi_library (dbi_conn conn)
+dbi_library_test (dbi_conn conn)
{
gint64 testlonglong = -9223372036854775807LL, resultlonglong = 0;
guint64 testulonglong = 9223372036854775807LLU, resultulonglong = 0;
@@ -1777,5 +1687,28 @@ conn_test_dbi_library (dbi_conn conn)
return retval;
}
+static bool
+conn_test_dbi_library(dbi_conn conn, QofBackend* qbe)
+{
+ auto result = dbi_library_test (conn);
+ switch (result)
+ {
+ case GNC_DBI_PASS:
+ break;
+
+ case GNC_DBI_FAIL_SETUP:
+ qof_backend_set_error (qbe, ERR_SQL_DBI_UNTESTABLE);
+ qof_backend_set_message (qbe,
+ "DBI library large number test incomplete");
+ break;
+
+ case GNC_DBI_FAIL_TEST:
+ qof_backend_set_error (qbe, ERR_SQL_BAD_DBI);
+ qof_backend_set_message (qbe,
+ "DBI library fails large number test");
+ break;
+ }
+ return result == GNC_DBI_PASS;
+}
/* ========================== END OF FILE ===================== */
commit 5074bd590fdf9604781b1cf193e2f6a40a793d2f
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 26 13:28:22 2016 -0700
Don't leak the quoted string returned from dbi_conn_quote_string_copy.
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index aa53d6a..c866cb5 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -414,14 +414,11 @@ GncDbiSqlConnection::quote_string (const std::string& unquoted_str)
size = dbi_conn_quote_string_copy (m_conn, unquoted_str.c_str(),
"ed_str);
- if (size != 0)
- {
- return std::string{quoted_str};
- }
- else
- {
+ if (quoted_str == nullptr)
return std::string{""};
- }
+ std::string retval{quoted_str};
+ free(quoted_str);
+ return retval;
}
commit b38be9fe20689cdc0e1e6dac4236de47d5e70ce1
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 26 11:50:51 2016 -0700
Get rid of gotos.
By replacing all of the char*s on the heap to std::strings, mostly in
a new UriString struct. Also lets us simplify the call to
set_standard_connection_options.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index abefc32..de41bd7 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -135,6 +135,50 @@ public:
/* ================================================================= */
/* ================================================================= */
+struct UriStrings
+{
+ UriStrings(const std::string& uri);
+ std::string basename() const noexcept;
+ const char* dbname() const noexcept;
+ std::string m_protocol;
+ std::string m_host;
+ std::string m_dbname;
+ std::string m_username;
+ std::string m_password;
+ std::string m_basename;
+ int m_portnum;
+};
+
+UriStrings::UriStrings(const std::string& uri)
+{
+ gchar *protocol, *host, *username, *password, *dbname;
+ int portnum;
+ gnc_uri_get_components(uri.c_str(), &protocol, &host, &portnum, &username,
+ &password, &dbname);
+ m_protocol = std::string{protocol};
+ m_host = std::string{host};
+ m_dbname = std::string{dbname};
+ m_username = std::string{username};
+ m_password = std::string{password};
+ m_portnum = portnum;
+ g_free(protocol);
+ g_free(host);
+ g_free(username);
+ g_free(password);
+ g_free(dbname);
+}
+
+std::string
+UriStrings::basename() const noexcept
+{
+ return m_protocol + "_" + m_host + "_" + m_username + "_" + m_dbname;
+}
+
+const char*
+UriStrings::dbname() const noexcept
+{
+ return m_dbname.c_str();
+}
static void
create_tables(const OBEEntry& entry, GncDbiBackend* be)
@@ -183,14 +227,11 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
gint result;
- gchar* dirname = nullptr;
- gchar* basename = nullptr;
- gchar* filepath = nullptr;
const char* msg = nullptr;
gboolean file_exists;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
PairVec options;
-
+
g_return_if_fail (qbe != nullptr);
g_return_if_fail (session != nullptr);
g_return_if_fail (book_id != nullptr);
@@ -198,16 +239,20 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
ENTER (" ");
/* Remove uri type if present */
- filepath = gnc_uri_get_path (book_id);
+ auto path = gnc_uri_get_path (book_id);
+ std::string filepath{path};
+ g_free(path);
GFileTest ftest = static_cast<decltype (ftest)> (
G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS) ;
- file_exists = g_file_test (filepath, ftest);
+ file_exists = g_file_test (filepath.c_str(), ftest);
if (!create && !file_exists)
{
qof_backend_set_error (qbe, ERR_FILEIO_FILE_NOT_FOUND);
- qof_backend_set_message (qbe, "Sqlite3 file %s not found", filepath);
- PWARN ("Sqlite3 file %s not found", filepath);
- goto exit;
+ qof_backend_set_message (qbe, "Sqlite3 file %s not found",
+ filepath.c_str());
+ PWARN ("Sqlite3 file %s not found", filepath.c_str());
+ LEAVE("Error");
+ return;
}
if (create && !force && file_exists)
@@ -215,7 +260,8 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
msg = "Might clobber, no force";
PWARN ("%s", msg);
- goto exit;
+ LEAVE("Error");
+ return;
}
be->connect(nullptr);
@@ -233,24 +279,28 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to create sqlite3 dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
- goto exit;
+ LEAVE("Error");
+ return;
}
- dirname = g_path_get_dirname (filepath);
- basename = g_path_get_basename (filepath);
dbi_conn_error_handler (conn, sqlite3_error_fn, be);
/* dbi-sqlite3 documentation says that sqlite3 doesn't take a "host" option */
-
options.push_back(std::make_pair("host", "localhost"));
+ auto dirname = g_path_get_dirname (filepath.c_str());
+ auto basename = g_path_get_basename (filepath.c_str());
options.push_back(std::make_pair("dbname", basename));
options.push_back(std::make_pair("sqlite3_dbdir", dirname));
+ if (basename != nullptr) g_free (basename);
+ if (dirname != nullptr) g_free (dirname);
+
try {
set_options(conn, options);
}
catch (std::runtime_error& err)
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
result = dbi_conn_connect (conn);
@@ -258,7 +308,8 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to connect to %s: %d\n", book_id, result);
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
- goto exit;
+ LEAVE("Error");
+ return;
}
dbi_test_result = conn_test_dbi_library (conn);
@@ -286,16 +337,18 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
/* does now, and we don't want to */
dbi_conn_close (conn); /* leave it lying around. */
conn = nullptr;
- g_unlink (filepath);
+ g_unlink (filepath.c_str());
}
msg = "Bad DBI Library";
- goto exit;
+ LEAVE("Error");
+ return;
}
if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
{
qof_backend_set_error (qbe, ERR_BACKEND_LOCKED);
msg = "Locked";
- goto exit;
+ LEAVE("Error");
+ return;
}
be->connect(nullptr);
@@ -305,13 +358,9 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
/* We should now have a proper session set up.
* Let's start logging */
- xaccLogSetBaseName (filepath);
- PINFO ("logpath=%s", filepath ? filepath : "(null)");
+ xaccLogSetBaseName (filepath.c_str());
+ PINFO ("logpath=%s", filepath.c_str() ? filepath.c_str() : "(null)");
-exit:
- if (filepath != nullptr) g_free (filepath);
- if (basename != nullptr) g_free (basename);
- if (dirname != nullptr) g_free (dirname);
LEAVE ("%s", msg);
}
@@ -410,27 +459,25 @@ mysql_error_fn (dbi_conn conn, void* user_data)
*/
static bool
set_standard_connection_options (QofBackend* qbe, dbi_conn conn,
- const std::string& host, int port,
- const std::string& dbname,
- const std::string& username,
- const std::string& password)
+ const UriStrings& uri)
+
{
gint result;
PairVec options;
- options.push_back(std::make_pair("host", host));
- options.push_back(std::make_pair("dbname", dbname));
- options.push_back(std::make_pair("username", username));
- options.push_back(std::make_pair("password", password));
+ options.push_back(std::make_pair("host", uri.m_host));
+ options.push_back(std::make_pair("dbname", uri.m_dbname));
+ options.push_back(std::make_pair("username", uri.m_username));
+ options.push_back(std::make_pair("password", uri.m_password));
options.push_back(std::make_pair("encoding", "UTF-8"));
try
{
set_options(conn, options);
- auto result = dbi_conn_set_option_numeric(conn, "port", port);
+ auto result = dbi_conn_set_option_numeric(conn, "port", uri.m_portnum);
if (result < 0)
{
const char *msg = nullptr;
auto err = dbi_conn_error(conn, &msg);
- PERR("Error setting port option to %d: %s", port, msg);
+ PERR("Error setting port option to %d: %s", uri.m_portnum, msg);
throw std::runtime_error(msg);
}
}
@@ -636,20 +683,15 @@ adjust_sql_options (dbi_conn connection)
}
}
+
static void
gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
const gchar* book_id, gboolean ignore_lock,
gboolean create, gboolean force)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- gchar* protocol = nullptr;
- gchar* host = nullptr;
- gchar* dbname = nullptr;
- gchar* username = nullptr;
- gchar* password = nullptr;
gchar* basename = nullptr;
gchar* translog_path = nullptr;
- gint portnum = 0;
gint result;
gboolean success = FALSE;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
@@ -664,8 +706,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
/* Split the book-id
* Format is protocol://username:password@hostname:port/dbname
where username, password and port are optional) */
- gnc_uri_get_components (book_id, &protocol, &host, &portnum,
- &username, &password, &dbname);
+ UriStrings uri(book_id);
// Try to connect to the db. If it doesn't exist and the create
// flag is TRUE, we'll need to connect to the 'mysql' db and execute the
@@ -684,13 +725,14 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to create mysql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
- goto exit;
+ LEAVE("Error");
+ return;
}
dbi_conn_error_handler (conn, mysql_error_fn, be);
- if (!set_standard_connection_options (qbe, conn, host, portnum, dbname,
- username, password))
+ if (!set_standard_connection_options (qbe, conn, uri))
{
- goto exit;
+ LEAVE("Error");
+ return;
}
be->set_exists(true);
result = dbi_conn_connect (conn);
@@ -717,13 +759,15 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
}
if (GNC_DBI_PASS != dbi_test_result)
{
- goto exit;
+ LEAVE("Error");
+ return;
}
if (create && !force && save_may_clobber_data (qbe))
{
qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
PWARN ("Databse already exists, Might clobber it.");
- goto exit;
+ LEAVE("Error");
+ return;
}
success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
@@ -733,9 +777,10 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
if (be->exists())
{
- PERR ("Unable to connect to database '%s'\n", dbname);
+ PERR ("Unable to connect to database '%s'\n", uri.dbname());
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
// The db does not already exist. Connect to the 'mysql' db and try to create it.
@@ -749,7 +794,8 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
catch (std::runtime_error& err)
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
result = dbi_conn_connect (conn);
@@ -757,17 +803,19 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to connect to 'mysql' database\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
adjust_sql_options (conn);
auto dresult = dbi_conn_queryf (conn,
"CREATE DATABASE %s CHARACTER SET utf8",
- dbname);
+ uri.dbname());
if (dresult == nullptr)
{
- PERR ("Unable to create database '%s'\n", dbname);
+ PERR ("Unable to create database '%s'\n", uri.dbname());
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
dbi_conn_close (conn);
conn = nullptr;
@@ -786,20 +834,23 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to create mysql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
- goto exit;
+ LEAVE("Error");
+ return;
}
dbi_conn_error_handler (conn, mysql_error_fn, be);
- if (!set_standard_connection_options (qbe, conn, host, 0, dbname,
- username, password))
+ uri.m_portnum = 0;
+ if (!set_standard_connection_options (qbe, conn, uri))
{
- goto exit;
+ LEAVE("Error: Failed to set options.");
+ return;
}
result = dbi_conn_connect (conn);
if (result < 0)
{
- PERR ("Unable to create database '%s'\n", dbname);
+ PERR ("Unable to create database '%s'\n", uri.dbname());
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
adjust_sql_options (conn);
dbi_test_result = conn_test_dbi_library (conn);
@@ -822,21 +873,20 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
}
if (dbi_test_result != GNC_DBI_PASS)
{
- dbi_conn_queryf (conn, "DROP DATABASE %s", dbname);
- goto exit;
+ dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
+ return;
}
success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
}
else
{
qof_backend_set_error (qbe, ERR_BACKEND_NO_SUCH_DB);
- qof_backend_set_message (qbe, "Database %s not found", dbname);
+ qof_backend_set_message (qbe, "Database %s not found", uri.dbname());
}
}
if (success)
{
- dbi_result dresult;
be->connect(nullptr);
be->connect(
new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
@@ -845,19 +895,10 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
/* We should now have a proper session set up.
* Let's start logging */
- basename = g_strjoin ("_", protocol, host, username, dbname, nullptr);
- translog_path = gnc_build_translog_path (basename);
+ translog_path = gnc_build_translog_path (uri.basename().c_str());
xaccLogSetBaseName (translog_path);
PINFO ("logpath=%s", translog_path ? translog_path : "(null)");
-
-exit:
- g_free (protocol);
- g_free (host);
- g_free (username);
- g_free (password);
- g_free (basename);
g_free (translog_path);
- g_free (dbname);
LEAVE (" ");
}
@@ -968,15 +1009,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
gint result = 0;
- gchar* protocol = nullptr;
- gchar* host = nullptr;
- gchar* dbname = nullptr, *dbnamelc = nullptr;
- gchar* username = nullptr;
- gchar* password = nullptr;
- gchar* basename = nullptr;
- gchar* translog_path = nullptr;
gboolean success = FALSE;
- gint portnum = 0;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
PairVec options;
@@ -989,16 +1022,16 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
/* Split the book-id
* Format is protocol://username:password@hostname:port/dbname
where username, password and port are optional) */
- gnc_uri_get_components (book_id, &protocol, &host, &portnum,
- &username, &password, &dbname);
- if (portnum == 0)
- portnum = PGSQL_DEFAULT_PORT;
+ UriStrings uri(book_id);
+ if (uri.m_portnum == 0)
+ uri.m_portnum = PGSQL_DEFAULT_PORT;
/* Postgres's SQL interface coerces identifiers to lower case, but the
* C interface is case-sensitive. This results in a mixed-case dbname
* being created (with a lower case name) but then dbi can't conect to
* it. To work around this, coerce the name to lowercase first. */
- dbnamelc = g_utf8_strdown (dbname, -1);
-
+ auto lcname = g_utf8_strdown (uri.dbname(), -1);
+ uri.m_dbname = std::string{lcname};
+ g_free(lcname);
// Try to connect to the db. If it doesn't exist and the create
// flag is TRUE, we'll need to connect to the 'postgres' db and execute the
// CREATE DATABASE ddl statement there.
@@ -1017,13 +1050,14 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to create pgsql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
- goto exit;
+ LEAVE("Error");
+ return;
}
dbi_conn_error_handler (conn, pgsql_error_fn, be);
- if (!set_standard_connection_options (qbe, conn, host, portnum, dbnamelc,
- username, password))
+ if (!set_standard_connection_options (qbe, conn, uri))
{
- goto exit;
+ LEAVE("Error");
+ return;
}
be->set_exists(true);
result = dbi_conn_connect (conn);
@@ -1049,13 +1083,15 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
}
if (dbi_test_result != GNC_DBI_PASS)
{
- goto exit;
+ LEAVE("Error");
+ return;
}
if (create && !force && save_may_clobber_data (qbe))
{
qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
PWARN ("Databse already exists, Might clobber it.");
- goto exit;
+ LEAVE("Error");
+ return;
}
success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
@@ -1065,9 +1101,10 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
if (be->exists())
{
- PERR ("Unable to connect to database '%s'\n", dbname);
+ PERR ("Unable to connect to database '%s'\n", uri.dbname());
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
// The db does not already exist. Connect to the 'postgres' db and try to create it.
@@ -1081,7 +1118,8 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
catch (std::runtime_error& err)
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
result = dbi_conn_connect (conn);
@@ -1089,18 +1127,20 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to connect to 'postgres' database\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
auto dresult = dbi_conn_queryf (conn,
- "CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'", dbnamelc);
+ "CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'", uri.dbname());
if (dresult == nullptr)
{
- PERR ("Unable to create database '%s'\n", dbname);
+ PERR ("Unable to create database '%s'\n", uri.dbname());
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
dbi_conn_queryf (conn,
- "ALTER DATABASE %s SET standard_conforming_strings TO on", dbnamelc);
+ "ALTER DATABASE %s SET standard_conforming_strings TO on", uri.dbname());
dbi_conn_close (conn);
// Try again to connect to the db
@@ -1117,21 +1157,23 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
{
PERR ("Unable to create pgsql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
- goto exit;
+ LEAVE("Error");
+ return;
}
dbi_conn_error_handler (conn, pgsql_error_fn, be);
- if (!set_standard_connection_options (qbe, conn, host,
- PGSQL_DEFAULT_PORT,
- dbnamelc, username, password))
+ uri.m_portnum = PGSQL_DEFAULT_PORT;
+ if (!set_standard_connection_options (qbe, conn, uri))
{
- goto exit;
+ LEAVE("Error");
+ return;
}
result = dbi_conn_connect (conn);
if (result < 0)
{
- PERR ("Unable to create database '%s'\n", dbname);
+ PERR ("Unable to create database '%s'\n", uri.dbname());
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+ LEAVE("Error");
+ return;
}
dbi_test_result = conn_test_dbi_library (conn);
switch (dbi_test_result)
@@ -1154,15 +1196,16 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
if (GNC_DBI_PASS != dbi_test_result)
{
dbi_conn_select_db (conn, "template1");
- dbi_conn_queryf (conn, "DROP DATABASE %s", dbnamelc);
- goto exit;
+ dbi_conn_queryf (conn, "DROP DATABASE %s", uri.dbname());
+ LEAVE("Error");
+ return;
}
success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
}
else
{
qof_backend_set_error (qbe, ERR_BACKEND_NO_SUCH_DB);
- qof_backend_set_message (qbe, "Database %s not found", dbname);
+ qof_backend_set_message (qbe, "Database %s not found", uri.dbname());
}
}
if (success)
@@ -1175,20 +1218,10 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
/* We should now have a proper session set up.
* Let's start logging */
- basename = g_strjoin ("_", protocol, host, username, dbname, nullptr);
- translog_path = gnc_build_translog_path (basename);
+ auto translog_path = gnc_build_translog_path (uri.basename().c_str());
xaccLogSetBaseName (translog_path);
PINFO ("logpath=%s", translog_path ? translog_path : "(null)");
-
-exit:
- g_free (protocol);
- g_free (host);
- g_free (username);
- g_free (password);
- g_free (basename);
g_free (translog_path);
- g_free (dbname);
- g_free (dbnamelc);
LEAVE (" ");
}
commit d8556ca7b540cceb7aa82e75f63b518b797dc112
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 26 10:13:55 2016 -0700
Reformat adjust_sql_options a bit to reduce nesting.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index aa681fe..abefc32 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -595,48 +595,44 @@ static void
adjust_sql_options (dbi_conn connection)
{
dbi_result result = dbi_conn_query( connection, "SELECT @@sql_mode");
- if (result)
+ if (result == nullptr)
{
- dbi_result_first_row(result);
- std::string str{dbi_result_get_string_idx(result, 1)};
- if (str.empty())
- {
- const char* errmsg;
- int err = dbi_conn_error(connection, &errmsg);
- if (err)
- PERR("Unable to get sql_mode %d : %s", err, errmsg);
- else
- PINFO("Sql_mode isn't set.");
- }
+ const char* errmsg;
+ int err = dbi_conn_error(connection, &errmsg);
+ PERR("Unable to read sql_mode %d : %s", err, errmsg);
+ return;
+ }
+ dbi_result_first_row(result);
+ std::string str{dbi_result_get_string_idx(result, 1)};
+ dbi_result_free(result);
+ if (str.empty())
+ {
+ const char* errmsg;
+ int err = dbi_conn_error(connection, &errmsg);
+ if (err)
+ PERR("Unable to get sql_mode %d : %s", err, errmsg);
else
- {
- PINFO("Initial sql_mode: %s", str.c_str());
- if(str.find(SQL_OPTION_TO_REMOVE) != std::string::npos)
- {
- std::string adjusted_str{adjust_sql_options_string(str)};
- PINFO("Setting sql_mode to %s", adjusted_str.c_str());
- std::string set_str{"SET sql_mode=" + std::move(adjusted_str)};
- dbi_result set_result = dbi_conn_query(connection,
- set_str.c_str());
- if (set_result)
- {
- dbi_result_free(set_result);
- }
- else
- {
- const char* errmsg;
- int err = dbi_conn_error(connection, &errmsg);
- PERR("Unable to set sql_mode %d : %s", err, errmsg);
- }
- }
- }
- dbi_result_free(result);
+ PINFO("Sql_mode isn't set.");
+ return;
+ }
+ PINFO("Initial sql_mode: %s", str.c_str());
+ if(str.find(SQL_OPTION_TO_REMOVE) == std::string::npos)
+ return;
+
+ std::string adjusted_str{adjust_sql_options_string(str)};
+ PINFO("Setting sql_mode to %s", adjusted_str.c_str());
+ std::string set_str{"SET sql_mode=" + std::move(adjusted_str)};
+ dbi_result set_result = dbi_conn_query(connection,
+ set_str.c_str());
+ if (set_result)
+ {
+ dbi_result_free(set_result);
}
else
{
const char* errmsg;
int err = dbi_conn_error(connection, &errmsg);
- PERR("Unable to read sql_mode %d : %s", err, errmsg);
+ PERR("Unable to set sql_mode %d : %s", err, errmsg);
}
}
commit 431b704c92f4d2abc90b07ebc9a2c42c9a8a2d52
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 26 10:13:16 2016 -0700
Abstract setting database string-value options to function set_options.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index d235932..aa681fe 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -147,6 +147,24 @@ create_tables(const OBEEntry& entry, GncDbiBackend* be)
obe->create_tables (be);
}
+static void
+set_options(dbi_conn conn, const PairVec& options)
+{
+ for (auto option : options)
+ {
+ auto opt = option.first.c_str();
+ auto val = option.second.c_str();
+ auto result = dbi_conn_set_option(conn, opt, val);
+ if (result < 0)
+ {
+ const char *msg = nullptr;
+ int err = dbi_conn_error(conn, &msg);
+ PERR("Error setting %s option to %s: %s", opt, val, msg);
+ throw std::runtime_error(msg);
+ }
+ }
+}
+
void
sqlite3_error_fn (dbi_conn conn, void* user_data)
{
@@ -171,7 +189,8 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
const char* msg = nullptr;
gboolean file_exists;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
-
+ PairVec options;
+
g_return_if_fail (qbe != nullptr);
g_return_if_fail (session != nullptr);
g_return_if_fail (book_id != nullptr);
@@ -221,24 +240,15 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
basename = g_path_get_basename (filepath);
dbi_conn_error_handler (conn, sqlite3_error_fn, be);
/* dbi-sqlite3 documentation says that sqlite3 doesn't take a "host" option */
- result = dbi_conn_set_option (conn, "host", "localhost");
- if (result < 0)
- {
- PERR ("Error setting 'host' option\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
- }
- result = dbi_conn_set_option (conn, "dbname", basename);
- if (result < 0)
- {
- PERR ("Error setting 'dbname' option\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- goto exit;
+
+ options.push_back(std::make_pair("host", "localhost"));
+ options.push_back(std::make_pair("dbname", basename));
+ options.push_back(std::make_pair("sqlite3_dbdir", dirname));
+ try {
+ set_options(conn, options);
}
- result = dbi_conn_set_option (conn, "sqlite3_dbdir", dirname);
- if (result < 0)
+ catch (std::runtime_error& err)
{
- PERR ("Error setting 'sqlite3_dbdir' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
@@ -398,58 +408,40 @@ mysql_error_fn (dbi_conn conn, void* user_data)
* @param password Password
* @return TRUE if successful, FALSE if error
*/
-static gboolean
+static bool
set_standard_connection_options (QofBackend* qbe, dbi_conn conn,
- const gchar* host, int port,
- const gchar* dbname, const gchar* username, const gchar* password)
+ const std::string& host, int port,
+ const std::string& dbname,
+ const std::string& username,
+ const std::string& password)
{
gint result;
-
- result = dbi_conn_set_option (conn, "host", host);
- if (result < 0)
- {
- PERR ("Error setting 'host' option\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- return FALSE;
- }
- result = dbi_conn_set_option_numeric (conn, "port", port);
- if (result < 0)
- {
- PERR ("Error setting 'port' option\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- return FALSE;
- }
- result = dbi_conn_set_option (conn, "dbname", dbname);
- if (result < 0)
- {
- PERR ("Error setting 'dbname' option\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- return FALSE;
- }
- result = dbi_conn_set_option (conn, "username", username);
- if (result < 0)
- {
- PERR ("Error setting 'username' option\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- return FALSE;
- }
- result = dbi_conn_set_option (conn, "password", password);
- if (result < 0)
- {
- PERR ("Error setting 'password' option\n");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- return FALSE;
+ PairVec options;
+ options.push_back(std::make_pair("host", host));
+ options.push_back(std::make_pair("dbname", dbname));
+ options.push_back(std::make_pair("username", username));
+ options.push_back(std::make_pair("password", password));
+ options.push_back(std::make_pair("encoding", "UTF-8"));
+ try
+ {
+ set_options(conn, options);
+ auto result = dbi_conn_set_option_numeric(conn, "port", port);
+ if (result < 0)
+ {
+ const char *msg = nullptr;
+ auto err = dbi_conn_error(conn, &msg);
+ PERR("Error setting port option to %d: %s", port, msg);
+ throw std::runtime_error(msg);
+ }
}
-
- result = dbi_conn_set_option (conn, "encoding", "UTF-8");
- if (result < 0)
+ catch (std::runtime_error& err)
{
- PERR ("Error setting 'encoding' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- return FALSE;
+ return false;
}
- return TRUE;
+
+ return true;
}
/* FIXME: Move to GncDbiSqlConnection. */
@@ -616,27 +608,27 @@ adjust_sql_options (dbi_conn connection)
else
PINFO("Sql_mode isn't set.");
}
- else
+ else
{
- PINFO("Initial sql_mode: %s", str.c_str());
+ PINFO("Initial sql_mode: %s", str.c_str());
if(str.find(SQL_OPTION_TO_REMOVE) != std::string::npos)
{
- std::string adjusted_str{adjust_sql_options_string(str)};
- PINFO("Setting sql_mode to %s", adjusted_str.c_str());
- std::string set_str{"SET sql_mode=" + std::move(adjusted_str)};
- dbi_result set_result = dbi_conn_query(connection,
- set_str.c_str());
- if (set_result)
- {
- dbi_result_free(set_result);
- }
- else
- {
- const char* errmsg;
- int err = dbi_conn_error(connection, &errmsg);
- PERR("Unable to set sql_mode %d : %s", err, errmsg);
- }
- }
+ std::string adjusted_str{adjust_sql_options_string(str)};
+ PINFO("Setting sql_mode to %s", adjusted_str.c_str());
+ std::string set_str{"SET sql_mode=" + std::move(adjusted_str)};
+ dbi_result set_result = dbi_conn_query(connection,
+ set_str.c_str());
+ if (set_result)
+ {
+ dbi_result_free(set_result);
+ }
+ else
+ {
+ const char* errmsg;
+ int err = dbi_conn_error(connection, &errmsg);
+ PERR("Unable to set sql_mode %d : %s", err, errmsg);
+ }
+ }
}
dbi_result_free(result);
}
@@ -665,6 +657,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
gint result;
gboolean success = FALSE;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
+ PairVec options;
g_return_if_fail (qbe != nullptr);
g_return_if_fail (session != nullptr);
@@ -752,14 +745,17 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
// The db does not already exist. Connect to the 'mysql' db and try to create it.
if (create)
{
- dbi_result dresult;
- result = dbi_conn_set_option (conn, "dbname", "mysql");
- if (result < 0)
+ options.push_back(std::make_pair("dbname", "mysql"));
+ try
+ {
+ set_options(conn, options);
+ }
+ catch (std::runtime_error& err)
{
- PERR ("Error setting 'dbname' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
+
result = dbi_conn_connect (conn);
if (result < 0)
{
@@ -768,9 +764,9 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
goto exit;
}
adjust_sql_options (conn);
- dresult = dbi_conn_queryf (conn,
- "CREATE DATABASE %s CHARACTER SET utf8",
- dbname);
+ auto dresult = dbi_conn_queryf (conn,
+ "CREATE DATABASE %s CHARACTER SET utf8",
+ dbname);
if (dresult == nullptr)
{
PERR ("Unable to create database '%s'\n", dbname);
@@ -986,7 +982,8 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
gboolean success = FALSE;
gint portnum = 0;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
-
+ PairVec options;
+
g_return_if_fail (qbe != nullptr);
g_return_if_fail (session != nullptr);
g_return_if_fail (book_id != nullptr);
@@ -1080,14 +1077,17 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
// The db does not already exist. Connect to the 'postgres' db and try to create it.
if (create)
{
- dbi_result dresult;
- result = dbi_conn_set_option (conn, "dbname", "postgres");
- if (result < 0)
+ options.push_back(std::make_pair("dbname", "postgres"));
+ try
+ {
+ set_options(conn, options);
+ }
+ catch (std::runtime_error& err)
{
- PERR ("Error setting 'dbname' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
+
result = dbi_conn_connect (conn);
if (result < 0)
{
@@ -1095,8 +1095,8 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- dresult = dbi_conn_queryf (conn,
- "CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'", dbnamelc);
+ auto dresult = dbi_conn_queryf (conn,
+ "CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'", dbnamelc);
if (dresult == nullptr)
{
PERR ("Unable to create database '%s'\n", dbname);
commit ccc1cc49ab542fb96660d81af354e96c4a20c1e1
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jul 25 11:29:30 2016 -0700
Separate DBI classes into their own files.
diff --git a/src/backend/dbi/CMakeLists.txt b/src/backend/dbi/CMakeLists.txt
index be5fc15..af61474 100644
--- a/src/backend/dbi/CMakeLists.txt
+++ b/src/backend/dbi/CMakeLists.txt
@@ -5,10 +5,16 @@ ADD_SUBDIRECTORY(test)
# Source file gncmod-backend-dbi.c does not appear to be use in Makefile.in, so not included here.
SET (backend_dbi_SOURCES
- gnc-backend-dbi.cpp gnc-dbisqlconnection.cpp
+ gnc-backend-dbi.cpp
+ gnc-dbisqlresult.cpp
+ gnc-dbisqlconnection.cpp
)
SET (backend_dbi_noinst_HEADERS
- gnc-backend-dbi.h gnc-backend-dbi.hpp
+ gnc-backend-dbi.h
+ gnc-backend-dbi.hpp
+ gnc-dbisqlresult.hpp
+ gnc-dbisqlconnection.hpp
+ gnc-dbiprovider.hpp
)
# Add dependency on config.h
diff --git a/src/backend/dbi/Makefile.am b/src/backend/dbi/Makefile.am
index a2a2baa..800f5ee 100644
--- a/src/backend/dbi/Makefile.am
+++ b/src/backend/dbi/Makefile.am
@@ -22,11 +22,16 @@ AM_CPPFLAGS = \
libgncmod_backend_dbi_la_SOURCES = \
gnc-backend-dbi.cpp \
- gnc-dbisqlconnection.cpp
+ gnc-dbisqlconnection.cpp \
+ gnc-dbisqlresult.cpp
noinst_HEADERS = \
gnc-backend-dbi.h \
- gnc-backend-dbi.hpp
+ gnc-backend-dbi.hpp \
+ gnc-dbisqlconnection.hpp \
+ gnc-dbisqlresult.hpp \
+ gnc-dbiprovider.hpp \
+ gnc-dbiproviderimpl.hpp
libgncmod_backend_dbi_la_LDFLAGS = -shared -avoid-version
libgncmod_backend_dbi_la_LIBADD = \
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index b194b63..d235932 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -68,18 +68,17 @@ extern "C"
#include "splint-defs.h"
#endif
-
- /* For direct access to dbi data structs, sadly needed for datetime */
-#include <dbi/dbi-dev.h>
}
#include <boost/regex.hpp>
#include <string>
-#include <gnc-datetime.hpp>
#include <gnc-backend-prov.hpp>
#include "gnc-backend-dbi.h"
#include "gnc-backend-dbi.hpp"
+#include "gnc-dbisqlresult.hpp"
+#include "gnc-dbisqlconnection.hpp"
+
#if PLATFORM(WINDOWS)
#ifdef __STRICT_ANSI_UNSET__
#undef __STRICT_ANSI_UNSET__
@@ -99,6 +98,8 @@ static dbi_inst dbi_instance = nullptr;
#define TRANSACTION_NAME "trans"
static QofLogModule log_module = G_LOG_DOMAIN;
+// gnc-dbiproviderimpl.hpp has templates that need log_module defined.
+#include "gnc-dbiproviderimpl.hpp"
static gchar lock_table[] = "gnclock";
@@ -117,28 +118,6 @@ static gboolean save_may_clobber_data (QofBackend* qbe);
static GncDbiTestResult conn_test_dbi_library (dbi_conn conn);
-enum class DbType
-{
- DBI_SQLITE,
- DBI_MYSQL,
- DBI_PGSQL
-};
-
-
-template <DbType T>
-class GncDbiProviderImpl : public GncDbiProvider
-{
-public:
- std::string create_table_ddl(const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec);
- StrVec get_table_list(dbi_conn conn,
- const std::string& dbname);
- void append_col_def(std::string& ddl, const GncSqlColumnInfo& info);
- StrVec get_index_list (dbi_conn conn);
- void drop_index(dbi_conn conn, const std::string& index);
-};
-
template <DbType T>
class QofDbiBackendProvider : public QofBackendProvider
{
@@ -957,7 +936,6 @@ pgsql_error_fn (dbi_conn conn, void* user_data)
{
PINFO ("DBI error: %s\n", msg);
be->set_exists(false);
- be->set_error (ERR_BACKEND_NO_SUCH_DB, 0, FALSE);
}
else if (g_strrstr (msg,
"server closed the connection unexpectedly")) // Connection lost
@@ -971,17 +949,23 @@ pgsql_error_fn (dbi_conn conn, void* user_data)
be->set_error (ERR_BACKEND_CONN_LOST, 1, true);
be->retry_connection(msg);
}
- else if (be->connected() &&
- (g_str_has_prefix (msg, "connection pointer is NULL") ||
- g_str_has_prefix (msg, "could not connect to server"))) // No connection
+ else if (g_str_has_prefix (msg, "connection pointer is NULL") ||
+ g_str_has_prefix (msg, "could not connect to server")) // No connection
{
- be->set_error(ERR_BACKEND_CANT_CONNECT, 1, true);
- be->retry_connection (msg);
+
+ if (!be->connected())
+ qof_backend_set_error((QofBackend*)be, ERR_BACKEND_CANT_CONNECT);
+ else
+ {
+ be->set_error(ERR_BACKEND_CANT_CONNECT, 1, true);
+ be->retry_connection (msg);
+ }
}
else
{
PERR ("DBI error: %s\n", msg);
- be->set_error (ERR_BACKEND_MISC, 0, false);
+ if (be->connected())
+ be->set_error (ERR_BACKEND_MISC, 0, false);
}
}
@@ -1678,387 +1662,6 @@ gnc_module_finalize_backend_dbi (void)
}
/* --------------------------------------------------------- */
-GncSqlRow&
-GncDbiSqlResult::IteratorImpl::operator++()
-{
- int status = dbi_result_next_row (m_inst->m_dbi_result);
- if (status)
- return m_inst->m_row;
- int error = m_inst->dberror();
- if (error == DBI_ERROR_BADIDX || error == 0) //ran off the end of the results
- return m_inst->m_sentinel;
- PERR("Error %d incrementing results iterator.", error);
- qof_backend_set_error (m_inst->m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
- return m_inst->m_sentinel;
-}
-
-int64_t
-GncDbiSqlResult::IteratorImpl::get_int_at_col(const char* col) const
-{
- auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
- if(type != DBI_TYPE_INTEGER)
- throw (std::invalid_argument{"Requested integer from non-integer column."});
- return dbi_result_get_longlong (m_inst->m_dbi_result, col);
-}
-
-float
-GncDbiSqlResult::IteratorImpl::get_float_at_col(const char* col) const
-{
- auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
- auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
- if(type != DBI_TYPE_DECIMAL ||
- (attrs & DBI_DECIMAL_SIZEMASK) != DBI_DECIMAL_SIZE4)
- throw (std::invalid_argument{"Requested float from non-float column."});
- gnc_push_locale (LC_NUMERIC, "C");
- auto retval = dbi_result_get_float(m_inst->m_dbi_result, col);
- gnc_pop_locale (LC_NUMERIC);
- return retval;
-}
-
-double
-GncDbiSqlResult::IteratorImpl::get_double_at_col(const char* col) const
-{
- auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
- auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
- if(type != DBI_TYPE_DECIMAL ||
- (attrs & DBI_DECIMAL_SIZEMASK) != DBI_DECIMAL_SIZE8)
- throw (std::invalid_argument{"Requested double from non-double column."});
- gnc_push_locale (LC_NUMERIC, "C");
- auto retval = dbi_result_get_double(m_inst->m_dbi_result, col);
- gnc_pop_locale (LC_NUMERIC);
- return retval;
-}
-
-std::string
-GncDbiSqlResult::IteratorImpl::get_string_at_col(const char* col) const
-{
- auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
- auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
- if(type != DBI_TYPE_STRING)
- throw (std::invalid_argument{"Requested string from non-string column."});
- gnc_push_locale (LC_NUMERIC, "C");
- auto strval = dbi_result_get_string(m_inst->m_dbi_result, col);
- if (strval == nullptr)
- {
- gnc_pop_locale (LC_NUMERIC);
- throw (std::invalid_argument{"Column empty."});
- }
- auto retval = std::string{strval};
- gnc_pop_locale (LC_NUMERIC);
- return retval;
-}
-time64
-GncDbiSqlResult::IteratorImpl::get_time64_at_col (const char* col) const
-{
- auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
- auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
- if (type != DBI_TYPE_DATETIME)
- throw (std::invalid_argument{"Requested double from non-double column."});
- gnc_push_locale (LC_NUMERIC, "C");
-#if HAVE_LIBDBI_TO_LONGLONG
- /* A less evil hack than the one equrie by libdbi-0.8, but
- * still necessary to work around the same bug.
- */
- auto retval = dbi_result_get_as_longlong(dbi_row->result,
- col_name);
-#else
- /* A seriously evil hack to work around libdbi bug #15
- * https://sourceforge.net/p/libdbi/bugs/15/. When libdbi
- * v0.9 is widely available this can be replaced with
- * dbi_result_get_as_longlong.
- * Note: 0.9 is available in Debian Jessie and Fedora 21.
- */
- auto result = (dbi_result_t*) (m_inst->m_dbi_result);
- auto row = dbi_result_get_currow (result);
- auto idx = dbi_result_get_field_idx (result, col) - 1;
- time64 retval = result->rows[row]->field_values[idx].d_datetime;
- if (retval < MINTIME || retval > MAXTIME)
- retval = 0;
-#endif //HAVE_LIBDBI_TO_LONGLONG
- gnc_pop_locale (LC_NUMERIC);
- return retval;
-}
-
-
-/* --------------------------------------------------------- */
-
-GncDbiSqlResult::~GncDbiSqlResult()
-{
- int status = dbi_result_free (m_dbi_result);
-
- if (status == 0)
- return;
-
- PERR ("Error %d in dbi_result_free() result.", dberror() );
- qof_backend_set_error (m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
-}
-
-GncSqlRow&
-GncDbiSqlResult::begin()
-{
-
- if (m_dbi_result == nullptr ||
- dbi_result_get_numrows(m_dbi_result) == 0)
- return m_sentinel;
- int status = dbi_result_first_row(m_dbi_result);
- if (status)
- return m_row;
- int error = dberror(); //
-
- if (error != DBI_ERROR_BADIDX) //otherwise just an empty result set
- {
- PERR ("Error %d in dbi_result_first_row()", dberror());
- qof_backend_set_error (m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
- }
- return m_sentinel;
-}
-
-uint64_t
-GncDbiSqlResult::size() const noexcept
-{
- return dbi_result_get_numrows(m_dbi_result);
-}
-
-/* --------------------------------------------------------- */
-
-template<> void
-GncDbiProviderImpl<DbType::DBI_SQLITE>::append_col_def(std::string& ddl,
- const GncSqlColumnInfo& info)
-{
- const char* type_name = nullptr;
-
- if (info.m_type == BCT_INT)
- {
- type_name = "integer";
- }
- else if (info.m_type == BCT_INT64)
- {
- type_name = "bigint";
- }
- else if (info.m_type == BCT_DOUBLE)
- {
- type_name = "float8";
- }
- else if (info.m_type == BCT_STRING || info.m_type == BCT_DATE
- || info.m_type == BCT_DATETIME)
- {
- type_name = "text";
- }
- else
- {
- PERR ("Unknown column type: %d\n", info.m_type);
- type_name = "";
- }
- ddl += (info.m_name + " " + type_name);
- if (info.m_size != 0)
- {
- ddl += "(" + std::to_string(info.m_size) + ")";
- }
- if (info.m_primary_key)
- {
- ddl += " PRIMARY KEY";
- }
- if (info.m_autoinc)
- {
- ddl += " AUTOINCREMENT";
- }
- if (info.m_not_null)
- {
- ddl += " NOT NULL";
- }
-}
-
-template <DbType P> std::string
-GncDbiProviderImpl<P>::create_table_ddl (const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec)
-{
- std::string ddl;
- unsigned int col_num = 0;
-
- g_return_val_if_fail (conn != nullptr, ddl);
- ddl += "CREATE TABLE " + table_name + "(";
- for (auto const& info : info_vec)
- {
- if (col_num++ != 0)
- {
- ddl += ", ";
- }
- append_col_def (ddl, info);
- }
- ddl += ")";
-
- return ddl;
-}
-
-template<> void
-GncDbiProviderImpl<DbType::DBI_MYSQL>::append_col_def (std::string& ddl,
- const GncSqlColumnInfo& info)
-{
- const char* type_name = nullptr;
-
- if (info.m_type == BCT_INT)
- {
- type_name = "integer";
- }
- else if (info.m_type == BCT_INT64)
- {
- type_name = "bigint";
- }
- else if (info.m_type == BCT_DOUBLE)
- {
- type_name = "double";
- }
- else if (info.m_type == BCT_STRING)
- {
- type_name = "varchar";
- }
- else if (info.m_type == BCT_DATE)
- {
- type_name = "date";
- }
- else if (info.m_type == BCT_DATETIME)
- {
- type_name = "TIMESTAMP NULL DEFAULT 0";
- }
- else
- {
- PERR ("Unknown column type: %d\n", info.m_type);
- type_name = "";
- }
- ddl += info.m_name + " " + type_name;
- if (info.m_size != 0 && info.m_type == BCT_STRING)
- {
- ddl += "(" + std::to_string(info.m_size) + ")";
- }
- if (info.m_unicode)
- {
- ddl += " CHARACTER SET utf8";
- }
- if (info.m_primary_key)
- {
- ddl += " PRIMARY KEY";
- }
- if (info.m_autoinc)
- {
- ddl += " AUTO_INCREMENT";
- }
- if (info.m_not_null)
- {
- ddl += " NOT NULL";
- }
-}
-
-
-template<> void
-GncDbiProviderImpl<DbType::DBI_PGSQL>::append_col_def (std::string& ddl,
- const GncSqlColumnInfo& info)
-{
- const char* type_name = nullptr;
-
- if (info.m_type == BCT_INT)
- {
- if (info.m_autoinc)
- {
- type_name = "serial";
- }
- else
- {
- type_name = "integer";
- }
- }
- else if (info.m_type == BCT_INT64)
- {
- type_name = "int8";
- }
- else if (info.m_type == BCT_DOUBLE)
-
- {
- type_name = "double precision";
- }
- else if (info.m_type == BCT_STRING)
- {
- type_name = "varchar";
- }
- else if (info.m_type == BCT_DATE)
- {
- type_name = "date";
- }
- else if (info.m_type == BCT_DATETIME)
- {
- type_name = "timestamp without time zone";
- }
- else
- {
- PERR ("Unknown column type: %d\n", info.m_type);
- type_name = "";
- }
- ddl += info.m_name + " " + type_name;
- if (info.m_size != 0 && info.m_type == BCT_STRING)
- {
- ddl += "(" + std::to_string(info.m_size) + ")";
- }
- if (info.m_primary_key)
- {
- ddl += " PRIMARY KEY";
- }
- if (info.m_not_null)
- {
- ddl += " NOT NULL";
- }
-}
-
-static StrVec
-conn_get_table_list (dbi_conn conn, const std::string& dbname)
-{
- StrVec retval;
- auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), nullptr);
- while (dbi_result_next_row (tables) != 0)
- {
- std::string table_name {dbi_result_get_string_idx (tables, 1)};
- retval.push_back(table_name);
- }
- dbi_result_free (tables);
- return retval;
-}
-
-template<> StrVec
-GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
- const std::string& dbname)
-{
- /* Return the list, but remove the tables that sqlite3 adds for
- * its own use. */
- auto list = conn_get_table_list (conn, dbname);
- auto end = std::remove(list.begin(), list.end(), "sqlite_sequence");
- list.erase(end, list.end());
- return list;
-}
-
-template<> StrVec
-GncDbiProviderImpl<DbType::DBI_MYSQL>::get_table_list (dbi_conn conn,
- const std::string& dbname)
-{
- return conn_get_table_list (conn, dbname);
-}
-
-template<> StrVec
-GncDbiProviderImpl<DbType::DBI_PGSQL>::get_table_list (dbi_conn conn,
- const std::string& dbname)
-{
- auto list = conn_get_table_list (conn, dbname);
- auto end = std::remove_if (list.begin(), list.end(),
- [](std::string& table_name){
- return table_name == "sql_features" ||
- table_name == "sql_implementation_info" ||
- table_name == "sql_languages" ||
- table_name == "sql_packages" ||
- table_name == "sql_parts" ||
- table_name == "sql_sizing" ||
- table_name == "sql_sizing_profiles";
- });
- list.erase(end, list.end());
- return list;
-}
/** Users discovered a bug in some distributions of libdbi, where if
* it is compiled on certain versions of gcc with the -ffast-math
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index 75e4c5e..b959f51 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -34,7 +34,8 @@ extern "C"
#define GETPID() getpid()
#endif
}
-#include <gnc-backend-sql.h>
+#include "gnc-backend-sql.h"
+
#define GNC_HOST_NAME_MAX 255
/**
@@ -67,20 +68,6 @@ typedef enum
GNC_DBI_FAIL_TEST
} GncDbiTestResult;
-class GncDbiProvider
-{
-public:
- virtual ~GncDbiProvider() = default;
- virtual std::string create_table_ddl(const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec) = 0;
- virtual std::vector<std::string> get_table_list(dbi_conn conn,
- const std::string& dbname) = 0;
- virtual void append_col_def(std::string& ddl,
- const GncSqlColumnInfo& info) = 0;
- virtual std::vector<std::string> get_index_list (dbi_conn conn) = 0;
- virtual void drop_index(dbi_conn conn, const std::string& index) = 0;
-};
/**
* Implementations of GncSqlBackend.
@@ -112,135 +99,12 @@ private:
bool m_exists; // Does the database exist?
};
-class GncDbiSqlConnection : public GncSqlConnection
-{
-public:
- GncDbiSqlConnection (GncDbiProvider* provider, QofBackend* qbe,
- dbi_conn conn, const char* lock_table) :
- m_qbe{qbe}, m_conn{conn}, m_provider{provider}, m_conn_ok{true},
- m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0}, m_retry{false},
- m_lock_table{lock_table} {}
- ~GncDbiSqlConnection() override;
- GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
- noexcept override;
- int execute_nonselect_statement (const GncSqlStatementPtr&)
- noexcept override;
- GncSqlStatementPtr create_statement_from_sql (const std::string&)
- const noexcept override;
- bool does_table_exist (const std::string&) const noexcept override;
- bool begin_transaction () noexcept override;
- bool rollback_transaction () const noexcept override;
- bool commit_transaction () const noexcept override;
- bool create_table (const std::string&, const ColVec&) const noexcept override;
- bool create_index (const std::string&, const std::string&, const EntryVec&)
- const noexcept override;
- bool add_columns_to_table (const std::string&, const ColVec&)
- const noexcept override;
- std::string quote_string (const std::string&) const noexcept override;
- int dberror() const noexcept override {
- return dbi_conn_error(m_conn, nullptr); }
- QofBackend* qbe () const noexcept { return m_qbe; }
- dbi_conn conn() const noexcept { return m_conn; }
- GncDbiProvider* provider() { return m_provider; }
- inline void set_error(int error, int repeat, bool retry) noexcept override
- {
- m_last_error = error;
- m_error_repeat = repeat;
- m_retry = retry;
- }
- inline void init_error() noexcept
- {
- set_error(ERR_BACKEND_NO_ERR, 0, false);
- }
- /** Check if the dbi connection is valid. If not attempt to re-establish it
- * Returns TRUE is there is a valid connection in the end or FALSE otherwise
- */
- bool verify() noexcept override;
- bool retry_connection(const char* msg) noexcept override;
- dbi_result table_manage_backup(const std::string& table_name, TableOpType op);
- /* FIXME: These three friend functions should really be members, but doing
- * that is too invasive just yet. */
- bool table_operation (const StrVec& table_name_list,
- TableOpType op) noexcept;
- std::string add_columns_ddl(const std::string& table_name,
- const ColVec& info_vec) const noexcept;
- friend void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
-
-private:
- QofBackend* m_qbe;
- dbi_conn m_conn;
- GncDbiProvider* m_provider;
- /** Used by the error handler routines to flag if the connection is ok to
- * use
- */
- bool m_conn_ok;
- /** Code of the last error that occurred. This is set in the error callback
- * function.
- */
- int m_last_error;
- /** Used in case of transient errors. After such error, another attempt at
- * the original call is allowed. error_repeat tracks the number of attempts
- * and can be used to prevent infinite loops.
- */
- int m_error_repeat;
- /** Signals the calling function that it should retry (the error handler
- * detected transient error and managed to resolve it, but it can't run the
- * original query)
- */
- gboolean m_retry;
- const char* m_lock_table;
- void unlock_database();
-
-};
void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
/* external access required for tests */
std::string adjust_sql_options_string(const std::string&);
-/**
- * An iterable wrapper for dbi_result; allows using C++11 range for.
- */
-class GncDbiSqlResult : public GncSqlResult
-{
-public:
- GncDbiSqlResult(const GncDbiSqlConnection* conn, dbi_result result) :
- m_conn{conn}, m_dbi_result{result}, m_iter{this}, m_row{&m_iter},
- m_sentinel{nullptr} {}
- ~GncDbiSqlResult();
- uint64_t size() const noexcept;
- int dberror() { return m_conn->dberror(); }
- GncSqlRow& begin();
- GncSqlRow& end() { return m_sentinel; }
-protected:
- class IteratorImpl : public GncSqlResult::IteratorImpl
- {
- public:
- ~IteratorImpl() = default;
- IteratorImpl(GncDbiSqlResult* inst) : m_inst{inst} {}
- virtual GncSqlRow& operator++();
- virtual GncSqlRow& operator++(int) { return ++(*this); };
- virtual GncSqlResult* operator*() { return m_inst; }
- virtual int64_t get_int_at_col (const char* col) const;
- virtual float get_float_at_col (const char* col) const;
- virtual double get_double_at_col (const char* col) const;
- virtual std::string get_string_at_col (const char* col)const;
- virtual time64 get_time64_at_col (const char* col) const;
- virtual bool is_col_null(const char* col) const noexcept
- {
- return dbi_result_field_is_null(m_inst->m_dbi_result, col);
- }
- private:
- GncDbiSqlResult* m_inst;
- };
-private:
- const GncDbiSqlConnection* m_conn;
- dbi_result m_dbi_result;
- IteratorImpl m_iter;
- GncSqlRow m_row;
- GncSqlRow m_sentinel;
-
-};
#endif //GNC_BACKEND_DBI_HPP
diff --git a/src/backend/dbi/gnc-dbisqlconnection.hpp b/src/backend/dbi/gnc-dbiprovider.hpp
similarity index 59%
copy from src/backend/dbi/gnc-dbisqlconnection.hpp
copy to src/backend/dbi/gnc-dbiprovider.hpp
index 64aedb0..21d749e 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.hpp
+++ b/src/backend/dbi/gnc-dbiprovider.hpp
@@ -1,5 +1,5 @@
/********************************************************************
- * gnc-dbisqlconnection.hpp: Encapsulate libdbi dbi_conn *
+ * gnc-dbiprovider.cpp: Encapsulate differences among Dbi backends. *
* *
* Copyright 2016 John Ralls <jralls at ceridwen.us> *
* *
@@ -20,10 +20,36 @@
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu at gnu.org *
\********************************************************************/
-#ifndef _GNC_DBISQLCONNECTION_HPP_
-#define _GNC_DBISQLCONNECTION_HPP_
+
+#ifndef __GNC_DBIPROVIDER_HPP__
+#define __GNC_DBIPROVIDER_HPP__
+
+extern "C"
+{
+#include <dbi/dbi.h>
+}
+#include <string>
+#include <vector>
+
/**
- * Encapsulate a libdbi dbi_conn connection.
+ * Provides the primary abstraction for different DBI backends.
*/
+class GncSqlConnection;
+struct GncSqlColumnInfo;
+using ColVec=std::vector<GncSqlColumnInfo>;
+
+class GncDbiProvider
+{
+public:
+ virtual ~GncDbiProvider() = default;
+ virtual std::string create_table_ddl(const GncSqlConnection* conn,
+ const std::string& table_name,
+ const ColVec& info_vec) = 0;
+ virtual StrVec get_table_list(dbi_conn conn, const std::string& dbname) = 0;
+ virtual void append_col_def(std::string& ddl,
+ const GncSqlColumnInfo& info) = 0;
+ virtual StrVec get_index_list (dbi_conn conn) = 0;
+ virtual void drop_index(dbi_conn conn, const std::string& index) = 0;
+};
-#endif //_GNC_DBISQLCONNECTION_HPP_
+#endif //__GNC_DBIPROVIDER_HPP__
diff --git a/src/backend/dbi/gnc-dbiproviderimpl.hpp b/src/backend/dbi/gnc-dbiproviderimpl.hpp
new file mode 100644
index 0000000..2b9103a
--- /dev/null
+++ b/src/backend/dbi/gnc-dbiproviderimpl.hpp
@@ -0,0 +1,293 @@
+/************************************************************************
+ * gnc-dbiproviderimpl.hpp: Encapsulate differences among Dbi backends. *
+ * *
+ * Copyright 2016 John Ralls <jralls at ceridwen.us> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\***********************************************************************/
+#ifndef __GNC_DBISQLPROVIDERIMPL_HPP__
+#define __GNC_DBISQLPROVIDERIMPL_HPP__
+#include <guid.hpp>
+extern "C"
+{
+#include <config.h>
+}
+#include "gnc-backend-dbi.hpp"
+#include "gnc-dbiprovider.hpp"
+
+enum class DbType
+{
+ DBI_SQLITE,
+ DBI_MYSQL,
+ DBI_PGSQL
+};
+
+template <DbType T>
+class GncDbiProviderImpl : public GncDbiProvider
+{
+public:
+ std::string create_table_ddl(const GncSqlConnection* conn,
+ const std::string& table_name,
+ const ColVec& info_vec);
+ StrVec get_table_list(dbi_conn conn,
+ const std::string& dbname);
+ void append_col_def(std::string& ddl, const GncSqlColumnInfo& info);
+ StrVec get_index_list (dbi_conn conn);
+ void drop_index(dbi_conn conn, const std::string& index);
+};
+
+template<> void
+GncDbiProviderImpl<DbType::DBI_SQLITE>::append_col_def(std::string& ddl,
+ const GncSqlColumnInfo& info)
+{
+ const char* type_name = nullptr;
+
+ if (info.m_type == BCT_INT)
+ {
+ type_name = "integer";
+ }
+ else if (info.m_type == BCT_INT64)
+ {
+ type_name = "bigint";
+ }
+ else if (info.m_type == BCT_DOUBLE)
+ {
+ type_name = "float8";
+ }
+ else if (info.m_type == BCT_STRING || info.m_type == BCT_DATE
+ || info.m_type == BCT_DATETIME)
+ {
+ type_name = "text";
+ }
+ else
+ {
+ PERR ("Unknown column type: %d\n", info.m_type);
+ type_name = "";
+ }
+ ddl += (info.m_name + " " + type_name);
+ if (info.m_size != 0)
+ {
+ ddl += "(" + std::to_string(info.m_size) + ")";
+ }
+ if (info.m_primary_key)
+ {
+ ddl += " PRIMARY KEY";
+ }
+ if (info.m_autoinc)
+ {
+ ddl += " AUTOINCREMENT";
+ }
+ if (info.m_not_null)
+ {
+ ddl += " NOT NULL";
+ }
+}
+
+template <DbType P> std::string
+GncDbiProviderImpl<P>::create_table_ddl (const GncSqlConnection* conn,
+ const std::string& table_name,
+ const ColVec& info_vec)
+{
+ std::string ddl;
+ unsigned int col_num = 0;
+
+ g_return_val_if_fail (conn != nullptr, ddl);
+ ddl += "CREATE TABLE " + table_name + "(";
+ for (auto const& info : info_vec)
+ {
+ if (col_num++ != 0)
+ {
+ ddl += ", ";
+ }
+ append_col_def (ddl, info);
+ }
+ ddl += ")";
+
+ return ddl;
+}
+
+template<> void
+GncDbiProviderImpl<DbType::DBI_MYSQL>::append_col_def (std::string& ddl,
+ const GncSqlColumnInfo& info)
+{
+ const char* type_name = nullptr;
+
+ if (info.m_type == BCT_INT)
+ {
+ type_name = "integer";
+ }
+ else if (info.m_type == BCT_INT64)
+ {
+ type_name = "bigint";
+ }
+ else if (info.m_type == BCT_DOUBLE)
+ {
+ type_name = "double";
+ }
+ else if (info.m_type == BCT_STRING)
+ {
+ type_name = "varchar";
+ }
+ else if (info.m_type == BCT_DATE)
+ {
+ type_name = "date";
+ }
+ else if (info.m_type == BCT_DATETIME)
+ {
+ type_name = "TIMESTAMP NULL DEFAULT 0";
+ }
+ else
+ {
+ PERR ("Unknown column type: %d\n", info.m_type);
+ type_name = "";
+ }
+ ddl += info.m_name + " " + type_name;
+ if (info.m_size != 0 && info.m_type == BCT_STRING)
+ {
+ ddl += "(" + std::to_string(info.m_size) + ")";
+ }
+ if (info.m_unicode)
+ {
+ ddl += " CHARACTER SET utf8";
+ }
+ if (info.m_primary_key)
+ {
+ ddl += " PRIMARY KEY";
+ }
+ if (info.m_autoinc)
+ {
+ ddl += " AUTO_INCREMENT";
+ }
+ if (info.m_not_null)
+ {
+ ddl += " NOT NULL";
+ }
+}
+
+
+template<> void
+GncDbiProviderImpl<DbType::DBI_PGSQL>::append_col_def (std::string& ddl,
+ const GncSqlColumnInfo& info)
+{
+ const char* type_name = nullptr;
+
+ if (info.m_type == BCT_INT)
+ {
+ if (info.m_autoinc)
+ {
+ type_name = "serial";
+ }
+ else
+ {
+ type_name = "integer";
+ }
+ }
+ else if (info.m_type == BCT_INT64)
+ {
+ type_name = "int8";
+ }
+ else if (info.m_type == BCT_DOUBLE)
+
+ {
+ type_name = "double precision";
+ }
+ else if (info.m_type == BCT_STRING)
+ {
+ type_name = "varchar";
+ }
+ else if (info.m_type == BCT_DATE)
+ {
+ type_name = "date";
+ }
+ else if (info.m_type == BCT_DATETIME)
+ {
+ type_name = "timestamp without time zone";
+ }
+ else
+ {
+ PERR ("Unknown column type: %d\n", info.m_type);
+ type_name = "";
+ }
+ ddl += info.m_name + " " + type_name;
+ if (info.m_size != 0 && info.m_type == BCT_STRING)
+ {
+ ddl += "(" + std::to_string(info.m_size) + ")";
+ }
+ if (info.m_primary_key)
+ {
+ ddl += " PRIMARY KEY";
+ }
+ if (info.m_not_null)
+ {
+ ddl += " NOT NULL";
+ }
+}
+
+static StrVec
+conn_get_table_list (dbi_conn conn, const std::string& dbname)
+{
+ StrVec retval;
+ auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), nullptr);
+ while (dbi_result_next_row (tables) != 0)
+ {
+ std::string table_name {dbi_result_get_string_idx (tables, 1)};
+ retval.push_back(table_name);
+ }
+ dbi_result_free (tables);
+ return retval;
+}
+
+template<> StrVec
+GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
+ const std::string& dbname)
+{
+ /* Return the list, but remove the tables that sqlite3 adds for
+ * its own use. */
+ auto list = conn_get_table_list (conn, dbname);
+ auto end = std::remove(list.begin(), list.end(), "sqlite_sequence");
+ list.erase(end, list.end());
+ return list;
+}
+
+template<> StrVec
+GncDbiProviderImpl<DbType::DBI_MYSQL>::get_table_list (dbi_conn conn,
+ const std::string& dbname)
+{
+ return conn_get_table_list (conn, dbname);
+}
+
+template<> StrVec
+GncDbiProviderImpl<DbType::DBI_PGSQL>::get_table_list (dbi_conn conn,
+ const std::string& dbname)
+{
+ auto list = conn_get_table_list (conn, dbname);
+ auto end = std::remove_if (list.begin(), list.end(),
+ [](std::string& table_name){
+ return table_name == "sql_features" ||
+ table_name == "sql_implementation_info" ||
+ table_name == "sql_languages" ||
+ table_name == "sql_packages" ||
+ table_name == "sql_parts" ||
+ table_name == "sql_sizing" ||
+ table_name == "sql_sizing_profiles";
+ });
+ list.erase(end, list.end());
+ return list;
+}
+
+#endif //__GNC_DBISQLPROVIDERIMPL_HPP__
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index fabc26f..aa53d6a 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -28,13 +28,12 @@ extern "C"
#include <platform.h>
#include <gnc-locale-utils.h>
}
-#include "gnc-backend-dbi.hpp"
+#include "gnc-dbisqlconnection.hpp"
static QofLogModule log_module = G_LOG_DOMAIN;
static const unsigned int DBI_MAX_CONN_ATTEMPTS = 5;
-
/* --------------------------------------------------------- */
class GncDbiSqlStatement : public GncSqlStatement
{
diff --git a/src/backend/dbi/gnc-dbisqlconnection.hpp b/src/backend/dbi/gnc-dbisqlconnection.hpp
index 64aedb0..547ae2b 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.hpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.hpp
@@ -22,8 +22,95 @@
\********************************************************************/
#ifndef _GNC_DBISQLCONNECTION_HPP_
#define _GNC_DBISQLCONNECTION_HPP_
+
+#include "gnc-backend-dbi.hpp"
+#include "gnc-dbisqlresult.hpp"
+#include "gnc-dbiprovider.hpp"
+
+class GncDbiProvider;
+
/**
* Encapsulate a libdbi dbi_conn connection.
*/
+class GncDbiSqlConnection : public GncSqlConnection
+{
+public:
+ GncDbiSqlConnection (GncDbiProvider* provider, QofBackend* qbe,
+ dbi_conn conn, const char* lock_table) :
+ m_qbe{qbe}, m_conn{conn}, m_provider{provider}, m_conn_ok{true},
+ m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0}, m_retry{false},
+ m_lock_table{lock_table} {}
+ ~GncDbiSqlConnection() override;
+ GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
+ noexcept override;
+ int execute_nonselect_statement (const GncSqlStatementPtr&)
+ noexcept override;
+ GncSqlStatementPtr create_statement_from_sql (const std::string&)
+ const noexcept override;
+ bool does_table_exist (const std::string&) const noexcept override;
+ bool begin_transaction () noexcept override;
+ bool rollback_transaction () const noexcept override;
+ bool commit_transaction () const noexcept override;
+ bool create_table (const std::string&, const ColVec&) const noexcept override;
+ bool create_index (const std::string&, const std::string&, const EntryVec&)
+ const noexcept override;
+ bool add_columns_to_table (const std::string&, const ColVec&)
+ const noexcept override;
+ std::string quote_string (const std::string&) const noexcept override;
+ int dberror() const noexcept override {
+ return dbi_conn_error(m_conn, nullptr); }
+ QofBackend* qbe () const noexcept { return m_qbe; }
+ dbi_conn conn() const noexcept { return m_conn; }
+ GncDbiProvider* provider() { return m_provider; }
+ inline void set_error(int error, int repeat, bool retry) noexcept override
+ {
+ m_last_error = error;
+ m_error_repeat = repeat;
+ m_retry = retry;
+ }
+ inline void init_error() noexcept
+ {
+ set_error(ERR_BACKEND_NO_ERR, 0, false);
+ }
+ /** Check if the dbi connection is valid. If not attempt to re-establish it
+ * Returns TRUE is there is a valid connection in the end or FALSE otherwise
+ */
+ bool verify() noexcept override;
+ bool retry_connection(const char* msg) noexcept override;
+ dbi_result table_manage_backup(const std::string& table_name, TableOpType op);
+ /* FIXME: These three friend functions should really be members, but doing
+ * that is too invasive just yet. */
+ bool table_operation (const StrVec& table_name_list,
+ TableOpType op) noexcept;
+ std::string add_columns_ddl(const std::string& table_name,
+ const ColVec& info_vec) const noexcept;
+ friend void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
+
+private:
+ QofBackend* m_qbe;
+ dbi_conn m_conn;
+ GncDbiProvider* m_provider;
+ /** Used by the error handler routines to flag if the connection is ok to
+ * use
+ */
+ bool m_conn_ok;
+ /** Code of the last error that occurred. This is set in the error callback
+ * function.
+ */
+ int m_last_error;
+ /** Used in case of transient errors. After such error, another attempt at
+ * the original call is allowed. error_repeat tracks the number of attempts
+ * and can be used to prevent infinite loops.
+ */
+ int m_error_repeat;
+ /** Signals the calling function that it should retry (the error handler
+ * detected transient error and managed to resolve it, but it can't run the
+ * original query)
+ */
+ gboolean m_retry;
+ const char* m_lock_table;
+ void unlock_database();
+
+};
#endif //_GNC_DBISQLCONNECTION_HPP_
diff --git a/src/backend/dbi/gnc-dbisqlresult.cpp b/src/backend/dbi/gnc-dbisqlresult.cpp
new file mode 100644
index 0000000..07e7fa3
--- /dev/null
+++ b/src/backend/dbi/gnc-dbisqlresult.cpp
@@ -0,0 +1,187 @@
+/********************************************************************
+ * gnc-dbisqlresult.cpp: Encapsulate libdbi dbi_result *
+ * *
+ * Copyright 2016 John Ralls <jralls at ceridwen.us> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+
+#include <guid.hpp>
+extern "C"
+{
+#include <config.h>
+#include <gnc-locale-utils.h>
+#include <dbi/dbi.h>
+/* For direct access to dbi data structs, sadly needed for datetime */
+#include <dbi/dbi-dev.h>
+}
+#include <gnc-datetime.hpp>
+#include <gnc-backend-sql.h>
+#include "gnc-dbisqlresult.hpp"
+#include "gnc-dbisqlconnection.hpp"
+
+static QofLogModule log_module = G_LOG_DOMAIN;
+
+GncDbiSqlResult::~GncDbiSqlResult()
+{
+ int status = dbi_result_free (m_dbi_result);
+
+ if (status == 0)
+ return;
+
+ PERR ("Error %d in dbi_result_free() result.", m_conn->dberror() );
+ qof_backend_set_error (m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
+}
+
+int
+GncDbiSqlResult::dberror() const noexcept
+{
+ return m_conn->dberror();
+}
+
+GncSqlRow&
+GncDbiSqlResult::begin()
+{
+
+ if (m_dbi_result == nullptr ||
+ dbi_result_get_numrows(m_dbi_result) == 0)
+ return m_sentinel;
+ int status = dbi_result_first_row(m_dbi_result);
+ if (status)
+ return m_row;
+ int error = dberror(); //
+
+ if (error != DBI_ERROR_BADIDX) //otherwise just an empty result set
+ {
+ PERR ("Error %d in dbi_result_first_row()", dberror());
+ qof_backend_set_error (m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
+ }
+ return m_sentinel;
+}
+
+uint64_t
+GncDbiSqlResult::size() const noexcept
+{
+ return dbi_result_get_numrows(m_dbi_result);
+}
+/* --------------------------------------------------------- */
+
+GncSqlRow&
+GncDbiSqlResult::IteratorImpl::operator++()
+{
+ int status = dbi_result_next_row (m_inst->m_dbi_result);
+ if (status)
+ return m_inst->m_row;
+ int error = m_inst->dberror();
+ if (error == DBI_ERROR_BADIDX || error == 0) //ran off the end of the results
+ return m_inst->m_sentinel;
+ PERR("Error %d incrementing results iterator.", error);
+ qof_backend_set_error (m_inst->m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
+ return m_inst->m_sentinel;
+}
+
+int64_t
+GncDbiSqlResult::IteratorImpl::get_int_at_col(const char* col) const
+{
+ auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
+ if(type != DBI_TYPE_INTEGER)
+ throw (std::invalid_argument{"Requested integer from non-integer column."});
+ return dbi_result_get_longlong (m_inst->m_dbi_result, col);
+}
+
+float
+GncDbiSqlResult::IteratorImpl::get_float_at_col(const char* col) const
+{
+ auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
+ auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
+ if(type != DBI_TYPE_DECIMAL ||
+ (attrs & DBI_DECIMAL_SIZEMASK) != DBI_DECIMAL_SIZE4)
+ throw (std::invalid_argument{"Requested float from non-float column."});
+ gnc_push_locale (LC_NUMERIC, "C");
+ auto retval = dbi_result_get_float(m_inst->m_dbi_result, col);
+ gnc_pop_locale (LC_NUMERIC);
+ return retval;
+}
+
+double
+GncDbiSqlResult::IteratorImpl::get_double_at_col(const char* col) const
+{
+ auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
+ auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
+ if(type != DBI_TYPE_DECIMAL ||
+ (attrs & DBI_DECIMAL_SIZEMASK) != DBI_DECIMAL_SIZE8)
+ throw (std::invalid_argument{"Requested double from non-double column."});
+ gnc_push_locale (LC_NUMERIC, "C");
+ auto retval = dbi_result_get_double(m_inst->m_dbi_result, col);
+ gnc_pop_locale (LC_NUMERIC);
+ return retval;
+}
+
+std::string
+GncDbiSqlResult::IteratorImpl::get_string_at_col(const char* col) const
+{
+ auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
+ auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
+ if(type != DBI_TYPE_STRING)
+ throw (std::invalid_argument{"Requested string from non-string column."});
+ gnc_push_locale (LC_NUMERIC, "C");
+ auto strval = dbi_result_get_string(m_inst->m_dbi_result, col);
+ if (strval == nullptr)
+ {
+ gnc_pop_locale (LC_NUMERIC);
+ throw (std::invalid_argument{"Column empty."});
+ }
+ auto retval = std::string{strval};
+ gnc_pop_locale (LC_NUMERIC);
+ return retval;
+}
+time64
+GncDbiSqlResult::IteratorImpl::get_time64_at_col (const char* col) const
+{
+ auto type = dbi_result_get_field_type (m_inst->m_dbi_result, col);
+ auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
+ if (type != DBI_TYPE_DATETIME)
+ throw (std::invalid_argument{"Requested double from non-double column."});
+ gnc_push_locale (LC_NUMERIC, "C");
+#if HAVE_LIBDBI_TO_LONGLONG
+ /* A less evil hack than the one equrie by libdbi-0.8, but
+ * still necessary to work around the same bug.
+ */
+ auto retval = dbi_result_get_as_longlong(dbi_row->result,
+ col_name);
+#else
+ /* A seriously evil hack to work around libdbi bug #15
+ * https://sourceforge.net/p/libdbi/bugs/15/. When libdbi
+ * v0.9 is widely available this can be replaced with
+ * dbi_result_get_as_longlong.
+ * Note: 0.9 is available in Debian Jessie and Fedora 21.
+ */
+ auto result = (dbi_result_t*) (m_inst->m_dbi_result);
+ auto row = dbi_result_get_currow (result);
+ auto idx = dbi_result_get_field_idx (result, col) - 1;
+ time64 retval = result->rows[row]->field_values[idx].d_datetime;
+ if (retval < MINTIME || retval > MAXTIME)
+ retval = 0;
+#endif //HAVE_LIBDBI_TO_LONGLONG
+ gnc_pop_locale (LC_NUMERIC);
+ return retval;
+}
+
+
+/* --------------------------------------------------------- */
+
diff --git a/src/backend/dbi/gnc-dbisqlresult.hpp b/src/backend/dbi/gnc-dbisqlresult.hpp
new file mode 100644
index 0000000..acb658d
--- /dev/null
+++ b/src/backend/dbi/gnc-dbisqlresult.hpp
@@ -0,0 +1,77 @@
+/********************************************************************
+ * gnc-dbisqlresult.hpp: Iterable wrapper for dbi_result. *
+ * *
+ * Copyright 2016 John Ralls <jralls at ceridwen.us *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+
+/* Private structures and variables for gnc-backend-dbi.c and its unit tests */
+#ifndef __GNC_DBISQLBACKEND_HPP__
+#define __GNC_DBISQLBACKEND_HPP__
+
+#include "gnc-backend-dbi.h"
+
+class GncDbiSqlConnection;
+
+/**
+ * An iterable wrapper for dbi_result; allows using C++11 range for.
+ */
+class GncDbiSqlResult : public GncSqlResult
+{
+public:
+ GncDbiSqlResult(const GncDbiSqlConnection* conn, dbi_result result) :
+ m_conn{conn}, m_dbi_result{result}, m_iter{this}, m_row{&m_iter},
+ m_sentinel{nullptr} {}
+ ~GncDbiSqlResult();
+ uint64_t size() const noexcept;
+ int dberror() const noexcept;
+ GncSqlRow& begin();
+ GncSqlRow& end() { return m_sentinel; }
+protected:
+ class IteratorImpl : public GncSqlResult::IteratorImpl
+ {
+ public:
+ ~IteratorImpl() = default;
+ IteratorImpl(GncDbiSqlResult* inst) : m_inst{inst} {}
+ virtual GncSqlRow& operator++();
+ virtual GncSqlRow& operator++(int) { return ++(*this); };
+ virtual GncSqlResult* operator*() { return m_inst; }
+ virtual int64_t get_int_at_col (const char* col) const;
+ virtual float get_float_at_col (const char* col) const;
+ virtual double get_double_at_col (const char* col) const;
+ virtual std::string get_string_at_col (const char* col)const;
+ virtual time64 get_time64_at_col (const char* col) const;
+ virtual bool is_col_null(const char* col) const noexcept
+ {
+ return dbi_result_field_is_null(m_inst->m_dbi_result, col);
+ }
+ private:
+ GncDbiSqlResult* m_inst;
+ };
+
+private:
+ const GncDbiSqlConnection* m_conn;
+ dbi_result m_dbi_result;
+ IteratorImpl m_iter;
+ GncSqlRow m_row;
+ GncSqlRow m_sentinel;
+
+};
+
+#endif //__GNC_DBISQLRESULT_HPP__
diff --git a/src/backend/dbi/test/CMakeLists.txt b/src/backend/dbi/test/CMakeLists.txt
index cc09d9d..68c859c 100644
--- a/src/backend/dbi/test/CMakeLists.txt
+++ b/src/backend/dbi/test/CMakeLists.txt
@@ -20,6 +20,7 @@ SET(test_dbi_backend_SOURCES
test-dbi-stuff.cpp
../gnc-backend-dbi.cpp
../gnc-dbisqlconnection.cpp
+ ../gnc-dbisqlresult.cpp
)
# This test does not work on Win32
diff --git a/src/backend/dbi/test/Makefile.am b/src/backend/dbi/test/Makefile.am
index cd6a5f4..50c5fb5 100644
--- a/src/backend/dbi/test/Makefile.am
+++ b/src/backend/dbi/test/Makefile.am
@@ -62,7 +62,8 @@ test_backend_dbi_SOURCES = \
test-dbi-stuff.cpp \
test-dbi-business-stuff.cpp \
../gnc-dbisqlconnection.cpp \
- ../gnc-backend-dbi.cpp
+ ../gnc-backend-dbi.cpp \
+ ../gnc-dbisqlresult.cpp
test_backend_dbi_CPPFLAGS = \
-DDBI_TEST_XML_FILENAME=\"${srcdir}/test-dbi.xml\" \
diff --git a/src/backend/sql/gnc-address-sql.cpp b/src/backend/sql/gnc-address-sql.cpp
index c60ff72..cd6dd70 100644
--- a/src/backend/sql/gnc-address-sql.cpp
+++ b/src/backend/sql/gnc-address-sql.cpp
@@ -84,7 +84,7 @@ GncSqlColumnTableEntryImpl<CT_ADDRESS>::load (const GncSqlBackend* be,
g_return_if_fail (be != NULL);
g_return_if_fail (pObject != NULL);
- auto addr = gncAddressCreate (be->book, QOF_INSTANCE(pObject));
+ auto addr = gncAddressCreate (be->book(), QOF_INSTANCE(pObject));
for (auto const& subtable_row : col_table)
{
diff --git a/src/backend/sql/gnc-transaction-sql.cpp b/src/backend/sql/gnc-transaction-sql.cpp
index 250c94d..1ac88ae 100644
--- a/src/backend/sql/gnc-transaction-sql.cpp
+++ b/src/backend/sql/gnc-transaction-sql.cpp
@@ -971,7 +971,7 @@ convert_query_term_to_sql (const GncSqlBackend* be, const gchar* fieldName,
query_date_t date_data = (query_date_t)pPredData;
auto datebuf = be->time64_to_string (date_data->date.tv_sec);
- g_string_append_printf (sql, "'%s'", datebuf);
+ g_string_append_printf (sql, "'%s'", datebuf.c_str());
}
else if (strcmp (pPredData->type_name, QOF_TYPE_INT32) == 0)
commit c2082bea99bdb5bf144daad675f155b34abeea79
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Jul 24 15:16:15 2016 -0700
Convert upgrade_table to member, remove some convenience functions.
To wit, gnc_sql_execute_select_sql, gnc_sql_execute_nonselect_sql,
gnc_sql_create_temp_table, and gnc_sql_create_select_statement.
diff --git a/src/backend/sql/gnc-account-sql.cpp b/src/backend/sql/gnc-account-sql.cpp
index 1ec57f5..5590ba3 100644
--- a/src/backend/sql/gnc-account-sql.cpp
+++ b/src/backend/sql/gnc-account-sql.cpp
@@ -224,19 +224,17 @@ GncSqlAccountBackend::load_all (GncSqlBackend* be)
pBook = be->book();
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- if (stmt == nullptr)
- {
- LEAVE ("stmt == NULL");
- return;
- }
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
for (auto row : *result)
load_single_account (be, row, &l_accounts_needing_parents);
- auto sql = g_strdup_printf ("SELECT DISTINCT guid FROM %s", TABLE_NAME);
- gnc_sql_slots_load_for_sql_subquery (be, sql, (BookLookupFn)xaccAccountLookup);
- g_free (sql);
+ sql.str("");
+ sql << "SELECT DISTINCT guid FROM " << TABLE_NAME;
+ gnc_sql_slots_load_for_sql_subquery (be, sql.str().c_str(),
+ (BookLookupFn)xaccAccountLookup);
/* While there are items on the list of accounts needing parents,
try to see if the parent has now been loaded. Theory says that if
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index ade1a20..1ba18bf 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -673,6 +673,50 @@ GncSqlBackend::set_table_version (const std::string& table_name,
return true;
}
+void
+GncSqlBackend::upgrade_table (const std::string& table_name,
+ const EntryVec& col_table) noexcept
+{
+ DEBUG ("Upgrading %s table\n", table_name.c_str());
+
+ auto temp_table_name = table_name + "_new";
+ create_table (temp_table_name, col_table);
+ std::stringstream sql;
+ sql << "INSERT INTO " << temp_table_name << " SELECT * FROM " << table_name;
+ auto stmt = create_statement_from_sql(sql.str());
+ execute_nonselect_statement(stmt);
+
+ sql.str("");
+ sql << "DROP TABLE " << table_name;
+ stmt = create_statement_from_sql(sql.str());
+ execute_nonselect_statement(stmt);
+
+ sql.str("");
+ sql << "ALTER TABLE " << temp_table_name << " RENAME TO " << table_name;
+ stmt = create_statement_from_sql(sql.str());
+ execute_nonselect_statement(stmt);
+}
+
+/* This is required because we're passing be->timespace_format to
+ * g_strdup_printf.
+ */
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+std::string
+GncSqlBackend::time64_to_string (time64 t) const noexcept
+{
+ auto tm = gnc_gmtime (&t);
+
+ auto year = tm->tm_year + 1900;
+
+ auto datebuf = g_strdup_printf (m_timespec_format,
+ year, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ gnc_tm_free (tm);
+ std::string date{datebuf};
+ g_free(datebuf);
+ return date;
+}
+#pragma GCC diagnostic warning "-Wformat-nonliteral"
void
gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
@@ -1657,30 +1701,6 @@ typedef void (*TimespecSetterFunc) (const gpointer, Timespec*);
#define TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
#define TIMESPEC_COL_SIZE (4+2+2+2+2+2)
-/* This is required because we're passing be->timespace_format to
- * g_strdup_printf.
- */
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-gchar*
-gnc_sql_convert_timespec_to_string (const GncSqlBackend* be, Timespec ts)
-{
- time64 time;
- struct tm* tm;
- gint year;
- gchar* datebuf;
-
- time = timespecToTime64 (ts);
- tm = gnc_gmtime (&time);
-
- year = tm->tm_year + 1900;
-
- datebuf = g_strdup_printf (be->timespec_format(),
- year, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
- gnc_tm_free (tm);
- return datebuf;
-}
-#pragma GCC diagnostic warning "-Wformat-nonliteral"
-
template<> void
GncSqlColumnTableEntryImpl<CT_TIMESPEC>::load (const GncSqlBackend* be,
GncSqlRow& row,
@@ -1764,9 +1784,8 @@ GncSqlColumnTableEntryImpl<CT_TIMESPEC>::add_to_query(const GncSqlBackend* be,
if (ts.tv_sec != 0 || ts.tv_nsec != 0)
{
- char* datebuf = gnc_sql_convert_timespec_to_string (be, ts);
- vec.emplace_back (std::make_pair (std::string{m_col_name},
- std::string{datebuf}));
+ auto datebuf = be->time64_to_string (ts.tv_sec);
+ vec.emplace_back (std::make_pair (std::string{m_col_name}, datebuf));
return;
}
}
@@ -2005,18 +2024,6 @@ gnc_sql_load_object (const GncSqlBackend* be, GncSqlRow& row,
}
/* ================================================================= */
-GncSqlStatementPtr
-gnc_sql_create_select_statement (GncSqlBackend* be, const gchar* table_name)
-{
- g_return_val_if_fail (be != NULL, NULL);
- g_return_val_if_fail (table_name != NULL, NULL);
-
- auto sql = g_strdup_printf ("SELECT * FROM %s", table_name);
- auto stmt = be->create_statement_from_sql(sql);
- g_free (sql);
- return stmt;
-}
-
static GncSqlStatementPtr
create_single_col_select_statement (GncSqlBackend* be,
const gchar* table_name,
@@ -2031,35 +2038,6 @@ create_single_col_select_statement (GncSqlBackend* be,
/* ================================================================= */
-
-GncSqlResultPtr
-gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql)
-{
- g_return_val_if_fail (be != NULL, NULL);
- g_return_val_if_fail (sql != NULL, NULL);
-
- auto stmt = be->create_statement_from_sql(sql);
- if (stmt == nullptr)
- {
- return nullptr;
- }
- return be->execute_select_statement (stmt);
-}
-
-gint
-gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql)
-{
- g_return_val_if_fail (be != NULL, 0);
- g_return_val_if_fail (sql != NULL, 0);
-
- auto stmt = be->create_statement_from_sql(sql);
- if (stmt == NULL)
- {
- return -1;
- }
- return be->execute_nonselect_statement (stmt);
-}
-
uint_t
gnc_sql_append_guids_to_sql (std::stringstream& sql, const InstanceVec& instances)
{
@@ -2316,48 +2294,6 @@ GncSqlObjectBackend::create_tables (GncSqlBackend* be)
"Table creation aborted.", m_table_name.c_str(), m_version, version);
}
-gboolean
-gnc_sql_create_temp_table (const GncSqlBackend* be, const gchar* table_name,
- const EntryVec& col_table)
-{
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
-
- return be->create_table (table_name, col_table);
-}
-
-/* Create a temporary table, copy the data from the old table, delete the
- old table, then rename the new one. */
-void
-gnc_sql_upgrade_table (GncSqlBackend* be, const gchar* table_name,
- const EntryVec& col_table)
-{
- gchar* sql;
- gchar* temp_table_name;
-
- g_return_if_fail (be != NULL);
- g_return_if_fail (table_name != NULL);
-
- DEBUG ("Upgrading %s table\n", table_name);
-
- temp_table_name = g_strdup_printf ("%s_new", table_name);
- (void)gnc_sql_create_temp_table (be, temp_table_name, col_table);
- sql = g_strdup_printf ("INSERT INTO %s SELECT * FROM %s",
- temp_table_name, table_name);
- (void)gnc_sql_execute_nonselect_sql (be, sql);
- g_free (sql);
-
- sql = g_strdup_printf ("DROP TABLE %s", table_name);
- (void)gnc_sql_execute_nonselect_sql (be, sql);
- g_free (sql);
-
- sql = g_strdup_printf ("ALTER TABLE %s RENAME TO %s", temp_table_name,
- table_name);
- (void)gnc_sql_execute_nonselect_sql (be, sql);
- g_free (sql);
- g_free (temp_table_name);
-}
-
/* ================================================================= */
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 4fe36a2..cdf72fc 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -21,7 +21,7 @@
/**
* @defgroup SQLBE SQL Backend Core
- @{
+ @{
*/
/** @addtogroup Columns Columns
@@ -112,13 +112,13 @@ public:
GncSqlResultPtr execute_select_statement(const GncSqlStatementPtr& stmt) const noexcept;
int execute_nonselect_statement(const GncSqlStatementPtr& stmt) const noexcept;
std::string quote_string(const std::string&) const noexcept;
- /**
- * Creates a table in the database
- *
- * @param table_name Table name
- * @param col_table DB table description
- * @return TRUE if successful, FALSE if unsuccessful
- */
+ /**
+ * Creates a table in the database
+ *
+ * @param table_name Table name
+ * @param col_table DB table description
+ * @return TRUE if successful, FALSE if unsuccessful
+ */
bool create_table(const std::string& table_name, const EntryVec& col_table) const noexcept;
/**
* Creates a table in the database and sets its version
@@ -150,8 +150,35 @@ public:
*/
bool add_columns_to_table(const std::string& table_name,
const EntryVec& col_table) const noexcept;
+ /**
+ * Upgrades a table to a new structure.
+ *
+ * The upgrade is done by creating a new table with the new structure,
+ * SELECTing the old data into the new table, deleting the old table, then
+ * renaming the new table. Therefore, this will only work if the new table
+ * structure is similar enough to the old table that the SELECT will work.
+ *
+ * @param table_name SQL table name
+ * @param col_table Column table
+ */
+ void upgrade_table (const std::string& table_name,
+ const EntryVec& col_table) noexcept;
+ /**
+ * Returns the version number for a DB table.
+ *
+ * @param table_name Table name
+ * @return Version number, or 0 if the table does not exist
+ */
uint_t get_table_version(const std::string& table_name) const noexcept;
bool set_table_version (const std::string& table_name, uint_t version) noexcept;
+ /**
+ * Converts a time64 value to a string value for the database.
+ *
+ * @param t time64 to be converted.
+ * @return String representation of the Timespec
+ */
+ std::string time64_to_string (time64 t) const noexcept;
+
QofBook* book() const noexcept { return m_book; }
bool pristine() const noexcept { return m_is_pristine_db; }
@@ -390,8 +417,8 @@ class GncSqlObjectBackend
public:
GncSqlObjectBackend (int version, const std::string& type,
const std::string& table, const EntryVec& vec) :
- m_table_name{table}, m_version{version}, m_type_name{type},
- m_col_table{vec} {}
+ m_table_name{table}, m_version{version}, m_type_name{type},
+ m_col_table{vec} {}
/**
* Load all objects of m_type in the database into memory.
* @param be The GncSqlBackend containing the database connection.
@@ -592,21 +619,21 @@ public:
QofIdTypeConst obj_name,
gpointer pObject, T get_ref)
const noexcept
- {
- g_return_if_fail (pObject != NULL);
-
- try
{
- GncGUID guid;
- auto val = row.get_string_at_col (m_col_name);
- (void)string_to_guid (val.c_str(), &guid);
- auto target = get_ref(&guid);
- if (target != nullptr)
- set_parameter (pObject, target, get_setter(obj_name),
- m_gobj_param_name);
+ g_return_if_fail (pObject != NULL);
+
+ try
+ {
+ GncGUID guid;
+ auto val = row.get_string_at_col (m_col_name);
+ (void)string_to_guid (val.c_str(), &guid);
+ auto target = get_ref(&guid);
+ if (target != nullptr)
+ set_parameter (pObject, target, get_setter(obj_name),
+ m_gobj_param_name);
+ }
+ catch (std::invalid_argument) {}
}
- catch (std::invalid_argument) {}
- }
protected:
template <typename T> T
@@ -676,7 +703,7 @@ public:
gpointer pObject) const noexcept override;
void add_to_table(const GncSqlBackend* be, ColVec& vec) const noexcept override;
void add_to_query(const GncSqlBackend* be, QofIdTypeConst obj_name,
- gpointer pObject, PairVec& vec) const noexcept override;
+ gpointer pObject, PairVec& vec) const noexcept override;
};
template <GncSqlObjectType Type>
@@ -845,25 +872,6 @@ gboolean gnc_sql_do_db_operation (GncSqlBackend* be,
gpointer pObject,
const EntryVec& table);
-/**
- * Executes an SQL SELECT statement from an SQL char string and returns the
- * result rows. If an error occurs, an entry is added to the log, an error
- * status is returned to qof and NULL is returned.
- *
- * @param be SQL backend struct
- * @param sql SQL SELECT string
- * @return Results, or NULL if an error has occured
- */
-GncSqlResultPtr gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql);
-
-/**
- * Executes an SQL non-SELECT statement from an SQL char string.
- *
- * @param be SQL backend struct
- * @param sql SQL non-SELECT string
- * @returns Number of rows affected, or -1 if an error has occured
- */
-gint gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql);
/**
* Loads a Gnucash object from the database.
@@ -893,20 +901,6 @@ gboolean gnc_sql_object_is_it_in_db (GncSqlBackend* be,
QofIdTypeConst obj_name,
const gpointer pObject,
const EntryVec& table );
-
-/**
- * Creates a temporary table in the database. A temporary table does not
- * have a version number added to the versions table.
- *
- * @param be SQL backend struct
- * @param table_name Table name
- * @param col_table DB table description
- * @return TRUE if successful, FALSE if unsuccessful
- */
-gboolean gnc_sql_create_temp_table (const GncSqlBackend* be,
- const gchar* table_name,
- const EntryVec& col_table);
-
/**
* Loads the object guid from a database row. The table must have a column
* named "guid" with type CT_GUID.
@@ -920,16 +914,6 @@ const GncGUID* gnc_sql_load_guid (const GncSqlBackend* be, GncSqlRow& row);
/**
- * Creates a basic SELECT statement for a table.
- *
- * @param be SQL backend struct
- * @param table_name Table name
- * @return Statement
- */
-GncSqlStatementPtr gnc_sql_create_select_statement (GncSqlBackend* be,
- const gchar* table_name);
-
-/**
* Appends the ascii strings for a list of GUIDs to the end of an SQL string.
*
* @param str SQL string
@@ -940,30 +924,6 @@ GncSqlStatementPtr gnc_sql_create_select_statement (GncSqlBackend* be,
uint_t gnc_sql_append_guids_to_sql (std::stringstream& sql,
const InstanceVec& instances);
-/**
- * Converts a Timespec value to a string value for the database.
- *
- * @param be SQL backend
- * @param ts Timespec to be converted
- * @return String representation of the Timespec
- */
-gchar* gnc_sql_convert_timespec_to_string (const GncSqlBackend* be,
- Timespec ts);
-
-/**
- * Upgrades a table to a new structure. The upgrade is done by creating a new
- * table with the new structure, SELECTing the old data into the new table,
- * deleting the old table, then renaming the new table. Therefore, this will
- * only work if the new table structure is similar enough to the old table that
- * the SELECT will work.
- *
- * @param be SQL backend
- * @param table_name SQL table name
- * @param col_table Column table
- */
-void gnc_sql_upgrade_table (GncSqlBackend* be, const gchar* table_name,
- const EntryVec& col_table);
-
void _retrieve_guid_ (gpointer pObject, gpointer pValue);
gpointer gnc_sql_compile_query (QofBackend* pBEnd, QofQuery* pQuery);
@@ -1058,5 +1018,5 @@ GncSqlColumnTableEntry::add_value_to_vec(const GncSqlBackend* be,
#endif /* GNC_BACKEND_SQL_H */
/**
- @} end of the SQL Backend Core doxygen group
+ @} end of the SQL Backend Core doxygen group
*/
diff --git a/src/backend/sql/gnc-bill-term-sql.cpp b/src/backend/sql/gnc-bill-term-sql.cpp
index e01d9a8..2317992 100644
--- a/src/backend/sql/gnc-bill-term-sql.cpp
+++ b/src/backend/sql/gnc-bill-term-sql.cpp
@@ -238,7 +238,9 @@ GncSqlBillTermBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
InstanceVec instances;
GList* l_billterms_needing_parents = NULL;
@@ -315,7 +317,7 @@ GncSqlBillTermBackend::create_tables (GncSqlBackend* be)
else if (version == 1)
{
/* Upgrade 64 bit int handling */
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Billterms table upgraded from version 1 to version %d\n",
diff --git a/src/backend/sql/gnc-book-sql.cpp b/src/backend/sql/gnc-book-sql.cpp
index 2e339c8..3fd70df 100644
--- a/src/backend/sql/gnc-book-sql.cpp
+++ b/src/backend/sql/gnc-book-sql.cpp
@@ -171,7 +171,9 @@ GncSqlBookBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, BOOK_TABLE);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << BOOK_TABLE;
+ auto stmt = be->create_statement_from_sql(sql.str());
if (stmt != nullptr)
{
auto result = be->execute_select_statement(stmt);
diff --git a/src/backend/sql/gnc-budget-sql.cpp b/src/backend/sql/gnc-budget-sql.cpp
index 47a2634..df8f2f5 100644
--- a/src/backend/sql/gnc-budget-sql.cpp
+++ b/src/backend/sql/gnc-budget-sql.cpp
@@ -236,19 +236,19 @@ static gboolean
delete_budget_amounts (GncSqlBackend* be, GncBudget* budget)
{
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
- gchar* sql;
g_return_val_if_fail (be != NULL, FALSE);
g_return_val_if_fail (budget != NULL, FALSE);
(void)guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (budget)),
guid_buf);
- sql = g_strdup_printf ("DELETE FROM %s WHERE budget_guid='%s'", AMOUNTS_TABLE,
- guid_buf);
- (void)gnc_sql_execute_nonselect_sql (be, sql);
- g_free (sql);
+ std::stringstream sql;
+ sql << "DELETE FROM " << AMOUNTS_TABLE << " WHERE budget_guid='"<<
+ guid_buf << "'";
+ auto stmt = be->create_statement_from_sql(sql.str());
+ be->execute_nonselect_statement(stmt);
- return TRUE;
+ return true;
}
/**
@@ -335,10 +335,9 @@ GncSqlBudgetBackend::load_all (GncSqlBackend* be)
InstanceVec instances;
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, BUDGET_TABLE);
- if (stmt == nullptr)
- return;
-
+ std::stringstream sql;
+ sql << "SELECT * FROM " << BUDGET_TABLE;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
for (auto row : *result)
{
diff --git a/src/backend/sql/gnc-commodity-sql.cpp b/src/backend/sql/gnc-commodity-sql.cpp
index 864b6bf..ca40e45 100644
--- a/src/backend/sql/gnc-commodity-sql.cpp
+++ b/src/backend/sql/gnc-commodity-sql.cpp
@@ -146,8 +146,9 @@ GncSqlCommodityBackend::load_all (GncSqlBackend* be)
gnc_commodity_table* pTable;
pTable = gnc_commodity_table_get_table (be->book());
- auto stmt = gnc_sql_create_select_statement (be, COMMODITIES_TABLE);
- if (stmt == nullptr) return;
+ std::stringstream sql;
+ sql << "SELECT * FROM " << COMMODITIES_TABLE;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
for (auto row : *result)
diff --git a/src/backend/sql/gnc-customer-sql.cpp b/src/backend/sql/gnc-customer-sql.cpp
index 5dfbed6..e398e51 100644
--- a/src/backend/sql/gnc-customer-sql.cpp
+++ b/src/backend/sql/gnc-customer-sql.cpp
@@ -126,7 +126,9 @@ GncSqlCustomerBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
InstanceVec instances;
@@ -157,7 +159,7 @@ GncSqlCustomerBackend::create_tables (GncSqlBackend* be)
else if (version == 1)
{
/* Upgrade 64 bit int handling */
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Customers table upgraded from version 1 to version %d\n",
diff --git a/src/backend/sql/gnc-employee-sql.cpp b/src/backend/sql/gnc-employee-sql.cpp
index 3922123..188824f 100644
--- a/src/backend/sql/gnc-employee-sql.cpp
+++ b/src/backend/sql/gnc-employee-sql.cpp
@@ -112,7 +112,9 @@ GncSqlEmployeeBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
InstanceVec instances;
@@ -144,7 +146,7 @@ GncSqlEmployeeBackend::create_tables (GncSqlBackend* be)
else if (version == 1)
{
/* Upgrade 64 bit int handling */
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Employees table upgraded from version 1 to version %d\n",
diff --git a/src/backend/sql/gnc-entry-sql.cpp b/src/backend/sql/gnc-entry-sql.cpp
index 8d778cb..00dd649 100644
--- a/src/backend/sql/gnc-entry-sql.cpp
+++ b/src/backend/sql/gnc-entry-sql.cpp
@@ -194,7 +194,9 @@ GncSqlEntryBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
InstanceVec instances;
@@ -228,7 +230,7 @@ GncSqlEntryBackend::create_tables (GncSqlBackend* be)
1->2: 64 bit int handling
2->3: "entered" -> "date_entered", and it can be NULL
*/
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Entries table upgraded from version %d to version %d\n", version,
diff --git a/src/backend/sql/gnc-invoice-sql.cpp b/src/backend/sql/gnc-invoice-sql.cpp
index c31a15d..a70c038 100644
--- a/src/backend/sql/gnc-invoice-sql.cpp
+++ b/src/backend/sql/gnc-invoice-sql.cpp
@@ -133,7 +133,9 @@ GncSqlInvoiceBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
InstanceVec instances;
@@ -167,7 +169,7 @@ GncSqlInvoiceBackend::create_tables (GncSqlBackend* be)
1->2: 64 bit int handling
2->3: invoice open date can be NULL
*/
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Invoices table upgraded from version %d to version %d\n", version,
diff --git a/src/backend/sql/gnc-job-sql.cpp b/src/backend/sql/gnc-job-sql.cpp
index e8c0a86..9c9af58 100644
--- a/src/backend/sql/gnc-job-sql.cpp
+++ b/src/backend/sql/gnc-job-sql.cpp
@@ -105,7 +105,9 @@ GncSqlJobBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
InstanceVec instances;
diff --git a/src/backend/sql/gnc-lots-sql.cpp b/src/backend/sql/gnc-lots-sql.cpp
index 893dcf7..e9bbf37 100644
--- a/src/backend/sql/gnc-lots-sql.cpp
+++ b/src/backend/sql/gnc-lots-sql.cpp
@@ -127,7 +127,9 @@ GncSqlLotsBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
if (stmt != nullptr)
{
auto result = be->execute_select_statement(stmt);
@@ -165,7 +167,7 @@ GncSqlLotsBackend::create_tables (GncSqlBackend* be)
Create a temporary table, copy the data from the old table, delete the
old table, then rename the new one. */
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Lots table upgraded from version 1 to version %d\n", TABLE_VERSION);
diff --git a/src/backend/sql/gnc-order-sql.cpp b/src/backend/sql/gnc-order-sql.cpp
index 2159575..dce9583 100644
--- a/src/backend/sql/gnc-order-sql.cpp
+++ b/src/backend/sql/gnc-order-sql.cpp
@@ -105,7 +105,9 @@ GncSqlOrderBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
InstanceVec instances;
diff --git a/src/backend/sql/gnc-price-sql.cpp b/src/backend/sql/gnc-price-sql.cpp
index 0ab58c4..84450c9 100644
--- a/src/backend/sql/gnc-price-sql.cpp
+++ b/src/backend/sql/gnc-price-sql.cpp
@@ -108,7 +108,9 @@ GncSqlPriceBackend::load_all (GncSqlBackend* be)
pBook = be->book();
pPriceDB = gnc_pricedb_get_db (pBook);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
if (stmt != nullptr)
{
auto result = be->execute_select_statement(stmt);
@@ -153,7 +155,7 @@ GncSqlPriceBackend::create_tables (GncSqlBackend* be)
else if (version == 1)
{
/* Upgrade 64 bit int handling */
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Prices table upgraded from version 1 to version %d\n", TABLE_VERSION);
diff --git a/src/backend/sql/gnc-recurrence-sql.cpp b/src/backend/sql/gnc-recurrence-sql.cpp
index cb79b69..c863735 100644
--- a/src/backend/sql/gnc-recurrence-sql.cpp
+++ b/src/backend/sql/gnc-recurrence-sql.cpp
@@ -388,17 +388,17 @@ upgrade_recurrence_table_1_2 (GncSqlBackend* be)
/* Step 2: insert a default value in the newly created column */
{
gchar* weekend_adj_str = recurrenceWeekendAdjustToString (WEEKEND_ADJ_NONE);
- gchar* update_query = g_strdup_printf ("UPDATE %s SET %s = '%s';",
- TABLE_NAME,
- weekend_adjust_col_table[0]->name(),
- weekend_adj_str);
- (void)gnc_sql_execute_nonselect_sql (be, update_query);
+ std::stringstream sql;
+ sql << "UPDATE " << TABLE_NAME << " SET " <<
+ weekend_adjust_col_table[0]->name() << "='" <<
+ weekend_adj_str << "'";
+ auto stmt = be->create_statement_from_sql(sql.str());
+ be->execute_nonselect_statement(stmt);
g_free (weekend_adj_str);
- g_free (update_query);
}
/* Step 3: rewrite the table, requiring the weekend_adj column to be non-null */
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
}
diff --git a/src/backend/sql/gnc-schedxaction-sql.cpp b/src/backend/sql/gnc-schedxaction-sql.cpp
index 53e7694..0705ec6 100644
--- a/src/backend/sql/gnc-schedxaction-sql.cpp
+++ b/src/backend/sql/gnc-schedxaction-sql.cpp
@@ -123,7 +123,9 @@ GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, SCHEDXACTION_TABLE);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << SCHEDXACTION_TABLE;
+ auto stmt = be->create_statement_from_sql(sql.str());
if (stmt == NULL) return;
auto result = be->execute_select_statement(stmt);
SchedXactions* sxes;
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index 195777b..05985eb 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -1017,7 +1017,7 @@ GncSqlSlotsBackend::create_tables (GncSqlBackend* be)
*/
if (version == 1)
{
- gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
+ be->upgrade_table(TABLE_NAME, col_table);
ok = be->create_index ("slots_guid_index", TABLE_NAME,
obj_guid_col_table);
if (!ok)
diff --git a/src/backend/sql/gnc-tax-table-sql.cpp b/src/backend/sql/gnc-tax-table-sql.cpp
index eca590e..da4beb0 100644
--- a/src/backend/sql/gnc-tax-table-sql.cpp
+++ b/src/backend/sql/gnc-tax-table-sql.cpp
@@ -294,7 +294,9 @@ GncSqlTaxTableBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
/* First time, create the query */
- auto stmt = gnc_sql_create_select_statement (be, TT_TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TT_TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
GList* tt_needing_parents = NULL;
@@ -341,7 +343,7 @@ GncSqlTaxTableBackend::create_tables (GncSqlBackend* be)
else if (version == 1)
{
/* Upgrade 64 bit int handling */
- gnc_sql_upgrade_table (be, TT_TABLE_NAME, tt_col_table);
+ be->upgrade_table(TT_TABLE_NAME, tt_col_table);
be->set_table_version (TT_TABLE_NAME, TT_TABLE_VERSION);
PINFO ("Taxtables table upgraded from version 1 to version %d\n",
TT_TABLE_VERSION);
@@ -356,7 +358,7 @@ GncSqlTaxTableBackend::create_tables (GncSqlBackend* be)
else if (version == 1)
{
/* Upgrade 64 bit int handling */
- gnc_sql_upgrade_table (be, TTENTRIES_TABLE_NAME, ttentries_col_table);
+ be->upgrade_table(TTENTRIES_TABLE_NAME, ttentries_col_table);
be->set_table_version (TTENTRIES_TABLE_NAME, TTENTRIES_TABLE_VERSION);
PINFO ("Taxtable entries table upgraded from version 1 to version %d\n",
TTENTRIES_TABLE_VERSION);
diff --git a/src/backend/sql/gnc-transaction-sql.cpp b/src/backend/sql/gnc-transaction-sql.cpp
index 74ddd1b..250c94d 100644
--- a/src/backend/sql/gnc-transaction-sql.cpp
+++ b/src/backend/sql/gnc-transaction-sql.cpp
@@ -492,7 +492,7 @@ GncSqlTransBackend::create_tables (GncSqlBackend* be)
1->2: 64 bit int handling
2->3: allow dates to be NULL
*/
- gnc_sql_upgrade_table (be, m_table_name.c_str(), tx_col_table);
+ be->upgrade_table(m_table_name.c_str(), tx_col_table);
be->set_table_version (m_table_name.c_str(), m_version);
PINFO ("Transactions table upgraded from version %d to version %d\n",
version, m_version);
@@ -522,7 +522,7 @@ GncSqlSplitBackend::create_tables (GncSqlBackend* be)
/* Upgrade:
1->2: 64 bit int handling
3->4: Split reconcile date can be NULL */
- gnc_sql_upgrade_table (be, m_table_name.c_str(), split_col_table);
+ be->upgrade_table(m_table_name.c_str(), split_col_table);
if (!be->create_index("splits_tx_guid_index",
m_table_name.c_str(),
tx_guid_col_table))
@@ -969,9 +969,8 @@ convert_query_term_to_sql (const GncSqlBackend* be, const gchar* fieldName,
else if (g_strcmp0 (pPredData->type_name, QOF_TYPE_DATE) == 0)
{
query_date_t date_data = (query_date_t)pPredData;
- gchar* datebuf;
- datebuf = gnc_sql_convert_timespec_to_string (be, date_data->date);
+ auto datebuf = be->time64_to_string (date_data->date.tv_sec);
g_string_append_printf (sql, "'%s'", datebuf);
}
diff --git a/src/backend/sql/gnc-vendor-sql.cpp b/src/backend/sql/gnc-vendor-sql.cpp
index 5aaa56b..c429f46 100644
--- a/src/backend/sql/gnc-vendor-sql.cpp
+++ b/src/backend/sql/gnc-vendor-sql.cpp
@@ -115,7 +115,9 @@ GncSqlVendorBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
- auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ std::stringstream sql;
+ sql << "SELECT * FROM " << TABLE_NAME;
+ auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement(stmt);
InstanceVec instances;
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index 27d3817..f2922c1 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -591,31 +591,29 @@ gnc_sql_add_objectref_guid_col_info_to_list (const GncSqlBackend* be,// 1
test_gnc_sql_add_objectref_guid_col_info_to_list (Fixture *fixture, gconstpointer pData)
{
}*/
-/* gnc_sql_convert_timespec_to_string
-gchar*
-gnc_sql_convert_timespec_to_string (const GncSqlBackend* be, Timespec ts)// C: 1 */
+/* GncDbiBackend::time64_to_string
+std::string
+GncDbiBackend::time64_to_string (time64 t)// C: 1 */
#define numtests 6
static void
-test_gnc_sql_convert_timespec_to_string ()
+test_time64_to_string ()
{
GncSqlBackend be {nullptr, nullptr, "%4d-%02d-%02d %02d:%02d:%02d"};
- const char* date[numtests] = {"1995-03-11 19:17:26",
+ const char* dates[numtests] = {"1995-03-11 19:17:26",
"2001-04-20 11:44:07",
"1964-02-29 09:15:23",
"1959-04-02 00:00:00",
"2043-11-22 05:32:45",
"2153-12-18 01:15:30"
};
- int i;
- for (i = 0; i < numtests; i++)
+
+ for (auto date : dates)
{
- Timespec ts = gnc_iso8601_to_timespec_gmt (date[i]);
- gchar* datestr = gnc_sql_convert_timespec_to_string (&be, ts);
- g_assert_cmpstr (date[i], == , datestr);
-
- g_free (datestr);
+ Timespec ts = gnc_iso8601_to_timespec_gmt (date);
+ auto datestr = be.time64_to_string (ts.tv_sec);
+ g_assert_cmpstr (date, == , datestr.c_str());
}
}
@@ -937,8 +935,8 @@ test_suite_gnc_backend_sql (void)
// GNC_TEST_ADD (suitename, "add value guid to vec", Fixture, nullptr, test_add_value_guid_to_vec, teardown);
// GNC_TEST_ADD (suitename, "gnc sql add gvalue objectref guid to slist", Fixture, nullptr, test_gnc_sql_add_objectref_guid_to_vec, teardown);
// GNC_TEST_ADD (suitename, "gnc sql add objectref guid col info to list", Fixture, nullptr, test_gnc_sql_add_objectref_guid_col_info_to_list, teardown);
- GNC_TEST_ADD_FUNC (suitename, "gnc sql convert timespec to string",
- test_gnc_sql_convert_timespec_to_string);
+ GNC_TEST_ADD_FUNC (suitename, "GncDbiBackend time64 to string",
+ test_time64_to_string);
// GNC_TEST_ADD (suitename, "load timespec", Fixture, nullptr, test_load_timespec, teardown);
// GNC_TEST_ADD (suitename, "add timespec col info to list", Fixture, nullptr, test_add_timespec_col_info_to_list, teardown);
// GNC_TEST_ADD (suitename, "add value timespec to vec", Fixture, nullptr, test_add_value_timespec_to_vec, teardown);
@@ -970,7 +968,6 @@ test_suite_gnc_backend_sql (void)
// GNC_TEST_ADD (suitename, "build update statement", Fixture, nullptr, test_build_update_statement, teardown);
// GNC_TEST_ADD (suitename, "build delete statement", Fixture, nullptr, test_build_delete_statement, teardown);
// GNC_TEST_ADD (suitename, "do create table", Fixture, nullptr, test_do_create_table, teardown);
-// GNC_TEST_ADD (suitename, "gnc sql create temp table", Fixture, nullptr, test_gnc_sql_create_temp_table, teardown);
// GNC_TEST_ADD (suitename, "gnc sql create index", Fixture, nullptr, test_gnc_sql_create_index, teardown);
// GNC_TEST_ADD (suitename, "gnc sql upgrade table", Fixture, nullptr, test_gnc_sql_upgrade_table, teardown);
// GNC_TEST_ADD (suitename, "gnc sql add columns to table", Fixture, nullptr, test_gnc_sql_add_columns_to_table, teardown);
commit 54acef27c2b265f14364c1a47808899c644f6f66
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Jul 24 12:12:27 2016 -0700
Remove a bunch of free functions already implemented as GncSqlBackend members.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 86755d8..b194b63 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -1301,16 +1301,14 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
gnc_sql_load (be, book, loadType);
- if (GNUCASH_RESAVE_VERSION > gnc_sql_get_table_version (be,
- "Gnucash"))
+ if (GNUCASH_RESAVE_VERSION > be->get_table_version("Gnucash"))
{
/* The database was loaded with an older database schema or
* data semantics. In order to ensure consistency, the whole
* thing needs to be saved anew. */
qof_backend_set_error (qbe, ERR_SQL_DB_TOO_OLD);
}
- else if (GNUCASH_RESAVE_VERSION < gnc_sql_get_table_version (be,
- "Gnucash-Resave"))
+ else if (GNUCASH_RESAVE_VERSION < be->get_table_version("Gnucash-Resave"))
{
/* Worse, the database was created with a newer version. We
* can't safely write to this database, so the user will have
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index acc7dad..75e4c5e 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -194,9 +194,6 @@ private:
};
void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
-std::string add_columns_ddl(const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec);
/* external access required for tests */
std::string adjust_sql_options_string(const std::string&);
diff --git a/src/backend/sql/gnc-account-sql.cpp b/src/backend/sql/gnc-account-sql.cpp
index 0831095..1ec57f5 100644
--- a/src/backend/sql/gnc-account-sql.cpp
+++ b/src/backend/sql/gnc-account-sql.cpp
@@ -230,7 +230,7 @@ GncSqlAccountBackend::load_all (GncSqlBackend* be)
LEAVE ("stmt == NULL");
return;
}
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
for (auto row : *result)
load_single_account (be, row, &l_accounts_needing_parents);
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index 7d61beb..ade1a20 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -504,6 +504,15 @@ GncSqlBackend::create_table(const std::string& table_name,
}
bool
+GncSqlBackend::create_table(const std::string& table_name, int table_version,
+ const EntryVec& col_table) noexcept
+{
+ if (create_table (table_name, col_table))
+ return set_table_version (table_name, table_version);
+ return false;
+}
+
+bool
GncSqlBackend::create_index(const std::string& index_name,
const std::string& table_name,
const EntryVec& col_table) const noexcept
@@ -2003,7 +2012,7 @@ gnc_sql_create_select_statement (GncSqlBackend* be, const gchar* table_name)
g_return_val_if_fail (table_name != NULL, NULL);
auto sql = g_strdup_printf ("SELECT * FROM %s", table_name);
- auto stmt = gnc_sql_create_statement_from_sql (be, sql);
+ auto stmt = be->create_statement_from_sql(sql);
g_free (sql);
return stmt;
}
@@ -2017,29 +2026,11 @@ create_single_col_select_statement (GncSqlBackend* be,
g_return_val_if_fail (table_name != NULL, NULL);
auto sql = std::string{"SELECT "} + table_row->name() + " FROM " + table_name;
- return gnc_sql_create_statement_from_sql (be, sql.c_str());
+ return be->create_statement_from_sql(sql.c_str());
}
/* ================================================================= */
-GncSqlResultPtr
-gnc_sql_execute_select_statement (GncSqlBackend* be,
- const GncSqlStatementPtr& stmt)
-{
-
- g_return_val_if_fail (be != NULL, NULL);
-
- return be->execute_select_statement (stmt);
-}
-
-GncSqlStatementPtr
-gnc_sql_create_statement_from_sql (GncSqlBackend* be, const gchar* sql)
-{
- g_return_val_if_fail (be != NULL, NULL);
- g_return_val_if_fail (sql != NULL, NULL);
-
- return be->create_statement_from_sql (sql);
-}
GncSqlResultPtr
gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql)
@@ -2047,7 +2038,7 @@ gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql)
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (sql != NULL, NULL);
- auto stmt = gnc_sql_create_statement_from_sql (be, sql);
+ auto stmt = be->create_statement_from_sql(sql);
if (stmt == nullptr)
{
return nullptr;
@@ -2061,7 +2052,7 @@ gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql)
g_return_val_if_fail (be != NULL, 0);
g_return_val_if_fail (sql != NULL, 0);
- auto stmt = gnc_sql_create_statement_from_sql (be, sql);
+ auto stmt = be->create_statement_from_sql(sql);
if (stmt == NULL)
{
return -1;
@@ -2122,11 +2113,10 @@ gnc_sql_object_is_it_in_db (GncSqlBackend* be, const gchar* table_name,
/* WHERE */
PairVec values{get_object_values(be, obj_name, pObject, table)};
stmt->add_where_cond(obj_name, values);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement (stmt);
if (result != NULL)
{
auto retval = result->size() > 0;
- delete result;
return retval;
}
return false;
@@ -2311,19 +2301,6 @@ GncSqlObjectBackend::commit (GncSqlBackend* be, QofInstance* inst)
}
/* ================================================================= */
-
-gboolean
-gnc_sql_create_table (GncSqlBackend* be, const gchar* table_name,
- int table_version, const EntryVec& col_table)
-{
- DEBUG ("Creating %s table\n", table_name);
-
- if (be->create_table (table_name, col_table))
- return be->set_table_version (table_name, table_version);
-
- return false;
-}
-
void
GncSqlObjectBackend::create_tables (GncSqlBackend* be)
{
@@ -2349,29 +2326,6 @@ gnc_sql_create_temp_table (const GncSqlBackend* be, const gchar* table_name,
return be->create_table (table_name, col_table);
}
-gboolean
-gnc_sql_create_index (const GncSqlBackend* be, const gchar* index_name,
- const gchar* table_name,
- const EntryVec& col_table)
-{
- gboolean ok;
-
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (index_name != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
-
- ok = be->create_index (index_name, table_name, col_table);
- return ok;
-}
-
-gint
-gnc_sql_get_table_version (const GncSqlBackend* be, const gchar* table_name)
-{
- g_return_val_if_fail (be != NULL, 0);
- g_return_val_if_fail (table_name != NULL, 0);
- return be->get_table_version(table_name);
-}
-
/* Create a temporary table, copy the data from the old table, delete the
old table, then rename the new one. */
void
@@ -2404,16 +2358,6 @@ gnc_sql_upgrade_table (GncSqlBackend* be, const gchar* table_name,
g_free (temp_table_name);
}
-/* Adds one or more columns to an existing table. */
-gboolean gnc_sql_add_columns_to_table (GncSqlBackend* be, const gchar* table_name,
- const EntryVec& new_col_table)
-{
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
-
- return be->add_columns_to_table(table_name, new_col_table);
-}
-
/* ================================================================= */
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 10227c4..4fe36a2 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -87,21 +87,70 @@ public:
* destroys the version info.
*/
void connect(GncSqlConnection *conn) noexcept;
+ /**
+ * Initializes DB table version information.
+ *
+ * @param be SQL backend struct
+ */
void init_version_info() noexcept;
bool reset_version_info() noexcept;
+ /**
+ * Finalizes DB table version information.
+ *
+ * @param be SQL backend struct
+ */
void finalize_version_info() noexcept;
/* FIXME: These are just pass-throughs of m_conn functions. */
GncSqlStatementPtr create_statement_from_sql(const std::string& str) const noexcept;
+ /** Executes an SQL SELECT statement and returns the result rows. If an
+ * error occurs, an entry is added to the log, an error status is returned
+ * to qof and nullptr is returned.
+ *
+ * @param statement Statement
+ * @return Results, or nullptr if an error has occured
+ */
GncSqlResultPtr execute_select_statement(const GncSqlStatementPtr& stmt) const noexcept;
int execute_nonselect_statement(const GncSqlStatementPtr& stmt) const noexcept;
std::string quote_string(const std::string&) const noexcept;
+ /**
+ * Creates a table in the database
+ *
+ * @param table_name Table name
+ * @param col_table DB table description
+ * @return TRUE if successful, FALSE if unsuccessful
+ */
bool create_table(const std::string& table_name, const EntryVec& col_table) const noexcept;
+ /**
+ * Creates a table in the database and sets its version
+ *
+ * @param table_name Table name
+ * @param table_version Table version
+ * @param col_table DB table description
+ * @return TRUE if successful, FALSE if unsuccessful
+ */
+ bool create_table(const std::string& table_name, int table_version,
+ const EntryVec& col_table) noexcept;
+ /**
+ * Creates an index in the database
+ *
+ * @param index_name Index name
+ * @param table_name Table name
+ * @param col_table Columns that the index should index
+ * @return TRUE if successful, FALSE if unsuccessful
+ */
bool create_index(const std::string& index_name,
const std::string& table_name,
const EntryVec& col_table) const noexcept;
+ /**
+ * Adds one or more columns to an existing table.
+ *
+ * @param table_name SQL table name
+ * @param new_col_table Column table for new columns
+ * @return TRUE if successful, FALSE if unsuccessful
+ */
bool add_columns_to_table(const std::string& table_name,
const EntryVec& col_table) const noexcept;
- unsigned int get_table_version(const std::string& table_name) const noexcept;
+ uint_t get_table_version(const std::string& table_name) const noexcept;
bool set_table_version (const std::string& table_name, uint_t version) noexcept;
QofBook* book() const noexcept { return m_book; }
@@ -797,18 +846,6 @@ gboolean gnc_sql_do_db_operation (GncSqlBackend* be,
const EntryVec& table);
/**
- * Executes an SQL SELECT statement and returns the result rows. If an error
- * occurs, an entry is added to the log, an error status is returned to qof and
- * NULL is returned.
- *
- * @param be SQL backend struct
- * @param statement Statement
- * @return Results, or NULL if an error has occured
- */
-GncSqlResultPtr gnc_sql_execute_select_statement (GncSqlBackend* be,
- const GncSqlStatementPtr& statement);
-
-/**
* Executes an SQL SELECT statement from an SQL char string and returns the
* result rows. If an error occurs, an entry is added to the log, an error
* status is returned to qof and NULL is returned.
@@ -829,16 +866,6 @@ GncSqlResultPtr gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql)
gint gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql);
/**
- * Creates a statement from an SQL char string.
- *
- * @param be SQL backend struct
- * @param sql SQL char string
- * @return Statement
- */
-GncSqlStatementPtr gnc_sql_create_statement_from_sql (GncSqlBackend* be,
- const gchar* sql);
-
-/**
* Loads a Gnucash object from the database.
*
* @param be SQL backend struct
@@ -868,34 +895,6 @@ gboolean gnc_sql_object_is_it_in_db (GncSqlBackend* be,
const EntryVec& table );
/**
- * Returns the version number for a DB table.
- *
- * @param be SQL backend struct
- * @param table_name Table name
- * @return Version number, or 0 if the table does not exist
- */
-gint gnc_sql_get_table_version (const GncSqlBackend* be,
- const gchar* table_name);
-
-gboolean gnc_sql_set_table_version (GncSqlBackend* be,
- const gchar* table_name,
- gint version);
-
-/**
- * Creates a table in the database
- *
- * @param be SQL backend struct
- * @param table_name Table name
- * @param table_version Table version
- * @param col_table DB table description
- * @return TRUE if successful, FALSE if unsuccessful
- */
-gboolean gnc_sql_create_table (GncSqlBackend* be,
- const gchar* table_name,
- gint table_version,
- const EntryVec& col_table);
-
-/**
* Creates a temporary table in the database. A temporary table does not
* have a version number added to the versions table.
*
@@ -909,18 +908,6 @@ gboolean gnc_sql_create_temp_table (const GncSqlBackend* be,
const EntryVec& col_table);
/**
- * Creates an index in the database
- *
- * @param be SQL backend struct
- * @param index_name Index name
- * @param table_name Table name
- * @param col_table Columns that the index should index
- * @return TRUE if successful, FALSE if unsuccessful
- */
-gboolean gnc_sql_create_index (const GncSqlBackend* be, const char* index_name,
- const char* table_name, const EntryVec& col_table);
-
-/**
* Loads the object guid from a database row. The table must have a column
* named "guid" with type CT_GUID.
*
@@ -954,20 +941,6 @@ uint_t gnc_sql_append_guids_to_sql (std::stringstream& sql,
const InstanceVec& instances);
/**
- * Initializes DB table version information.
- *
- * @param be SQL backend struct
- */
-void gnc_sql_init_version_info (GncSqlBackend* be);
-
-/**
- * Finalizes DB table version information.
- *
- * @param be SQL backend struct
- */
-void gnc_sql_finalize_version_info (GncSqlBackend* be);
-
-/**
* Converts a Timespec value to a string value for the database.
*
* @param be SQL backend
@@ -991,17 +964,6 @@ gchar* gnc_sql_convert_timespec_to_string (const GncSqlBackend* be,
void gnc_sql_upgrade_table (GncSqlBackend* be, const gchar* table_name,
const EntryVec& col_table);
-/**
- * Adds one or more columns to an existing table.
- *
- * @param be SQL backend
- * @param table_name SQL table name
- * @param new_col_table Column table for new columns
- * @return TRUE if successful, FALSE if unsuccessful
- */
-gboolean gnc_sql_add_columns_to_table (GncSqlBackend* be, const char* table_name,
- const EntryVec& new_col_table);
-
void _retrieve_guid_ (gpointer pObject, gpointer pValue);
gpointer gnc_sql_compile_query (QofBackend* pBEnd, QofQuery* pQuery);
diff --git a/src/backend/sql/gnc-bill-term-sql.cpp b/src/backend/sql/gnc-bill-term-sql.cpp
index 9b41b76..e01d9a8 100644
--- a/src/backend/sql/gnc-bill-term-sql.cpp
+++ b/src/backend/sql/gnc-bill-term-sql.cpp
@@ -239,7 +239,7 @@ GncSqlBillTermBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
InstanceVec instances;
GList* l_billterms_needing_parents = NULL;
@@ -307,10 +307,10 @@ GncSqlBillTermBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
- gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
}
else if (version == 1)
{
diff --git a/src/backend/sql/gnc-book-sql.cpp b/src/backend/sql/gnc-book-sql.cpp
index 5e4b4b5..2e339c8 100644
--- a/src/backend/sql/gnc-book-sql.cpp
+++ b/src/backend/sql/gnc-book-sql.cpp
@@ -174,7 +174,7 @@ GncSqlBookBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, BOOK_TABLE);
if (stmt != nullptr)
{
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
auto row = result->begin();
/* If there are no rows, try committing the book; unset
diff --git a/src/backend/sql/gnc-budget-sql.cpp b/src/backend/sql/gnc-budget-sql.cpp
index ddf05bd..47a2634 100644
--- a/src/backend/sql/gnc-budget-sql.cpp
+++ b/src/backend/sql/gnc-budget-sql.cpp
@@ -214,11 +214,11 @@ load_budget_amounts (GncSqlBackend* be, GncBudget* budget)
guid_buf);
auto sql = g_strdup_printf ("SELECT * FROM %s WHERE budget_guid='%s'",
AMOUNTS_TABLE, guid_buf);
- auto stmt = gnc_sql_create_statement_from_sql (be, sql);
+ auto stmt = be->create_statement_from_sql(sql);
g_free (sql);
if (stmt != nullptr)
{
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
budget_amount_info_t info = { budget, NULL, 0 };
for (auto row : *result)
@@ -339,7 +339,7 @@ GncSqlBudgetBackend::load_all (GncSqlBackend* be)
if (stmt == nullptr)
return;
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
for (auto row : *result)
{
auto b = load_single_budget (be, row);
@@ -359,16 +359,16 @@ GncSqlBudgetBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, BUDGET_TABLE);
+ version = be->get_table_version( BUDGET_TABLE);
if (version == 0)
{
- (void)gnc_sql_create_table (be, BUDGET_TABLE, TABLE_VERSION, col_table);
+ (void)be->create_table(BUDGET_TABLE, TABLE_VERSION, col_table);
}
- version = gnc_sql_get_table_version (be, AMOUNTS_TABLE);
+ version = be->get_table_version( AMOUNTS_TABLE);
if (version == 0)
{
- (void)gnc_sql_create_table (be, AMOUNTS_TABLE, AMOUNTS_TABLE_VERSION,
+ (void)be->create_table(AMOUNTS_TABLE, AMOUNTS_TABLE_VERSION,
budget_amounts_col_table);
}
}
diff --git a/src/backend/sql/gnc-commodity-sql.cpp b/src/backend/sql/gnc-commodity-sql.cpp
index 7b1ca5b..864b6bf 100644
--- a/src/backend/sql/gnc-commodity-sql.cpp
+++ b/src/backend/sql/gnc-commodity-sql.cpp
@@ -148,7 +148,7 @@ GncSqlCommodityBackend::load_all (GncSqlBackend* be)
pTable = gnc_commodity_table_get_table (be->book());
auto stmt = gnc_sql_create_select_statement (be, COMMODITIES_TABLE);
if (stmt == nullptr) return;
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
for (auto row : *result)
{
diff --git a/src/backend/sql/gnc-customer-sql.cpp b/src/backend/sql/gnc-customer-sql.cpp
index 91e3c49..5dfbed6 100644
--- a/src/backend/sql/gnc-customer-sql.cpp
+++ b/src/backend/sql/gnc-customer-sql.cpp
@@ -127,7 +127,7 @@ GncSqlCustomerBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
InstanceVec instances;
for (auto row : *result)
@@ -149,10 +149,10 @@ GncSqlCustomerBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
- gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
}
else if (version == 1)
{
diff --git a/src/backend/sql/gnc-employee-sql.cpp b/src/backend/sql/gnc-employee-sql.cpp
index a39e2ce..3922123 100644
--- a/src/backend/sql/gnc-employee-sql.cpp
+++ b/src/backend/sql/gnc-employee-sql.cpp
@@ -113,7 +113,7 @@ GncSqlEmployeeBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
InstanceVec instances;
@@ -136,10 +136,10 @@ GncSqlEmployeeBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
- gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
}
else if (version == 1)
{
diff --git a/src/backend/sql/gnc-entry-sql.cpp b/src/backend/sql/gnc-entry-sql.cpp
index f6d31ed..8d778cb 100644
--- a/src/backend/sql/gnc-entry-sql.cpp
+++ b/src/backend/sql/gnc-entry-sql.cpp
@@ -195,7 +195,7 @@ GncSqlEntryBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
InstanceVec instances;
for (auto row : *result)
@@ -217,10 +217,10 @@ GncSqlEntryBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
- gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
}
else if (version < TABLE_VERSION)
{
diff --git a/src/backend/sql/gnc-invoice-sql.cpp b/src/backend/sql/gnc-invoice-sql.cpp
index f1c14b2..c31a15d 100644
--- a/src/backend/sql/gnc-invoice-sql.cpp
+++ b/src/backend/sql/gnc-invoice-sql.cpp
@@ -134,7 +134,7 @@ GncSqlInvoiceBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
InstanceVec instances;
for (auto row : *result)
@@ -156,10 +156,10 @@ GncSqlInvoiceBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
- gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
}
else if (version < TABLE_VERSION)
{
diff --git a/src/backend/sql/gnc-job-sql.cpp b/src/backend/sql/gnc-job-sql.cpp
index 019c306..e8c0a86 100644
--- a/src/backend/sql/gnc-job-sql.cpp
+++ b/src/backend/sql/gnc-job-sql.cpp
@@ -106,7 +106,7 @@ GncSqlJobBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
InstanceVec instances;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-lots-sql.cpp b/src/backend/sql/gnc-lots-sql.cpp
index ce4fcda..893dcf7 100644
--- a/src/backend/sql/gnc-lots-sql.cpp
+++ b/src/backend/sql/gnc-lots-sql.cpp
@@ -130,7 +130,7 @@ GncSqlLotsBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
if (stmt != nullptr)
{
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
if (result->begin () == nullptr)
return;
for (auto row : *result)
@@ -151,11 +151,11 @@ GncSqlLotsBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
/* The table doesn't exist, so create it */
- (void)gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ (void)be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
}
else if (version == 1)
{
diff --git a/src/backend/sql/gnc-order-sql.cpp b/src/backend/sql/gnc-order-sql.cpp
index 7115f25..2159575 100644
--- a/src/backend/sql/gnc-order-sql.cpp
+++ b/src/backend/sql/gnc-order-sql.cpp
@@ -106,7 +106,7 @@ GncSqlOrderBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
InstanceVec instances;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-price-sql.cpp b/src/backend/sql/gnc-price-sql.cpp
index 7974eaf..0ab58c4 100644
--- a/src/backend/sql/gnc-price-sql.cpp
+++ b/src/backend/sql/gnc-price-sql.cpp
@@ -111,7 +111,7 @@ GncSqlPriceBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
if (stmt != nullptr)
{
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
if (result->begin() == result->end())
return;
@@ -145,10 +145,10 @@ GncSqlPriceBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
- (void)gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ (void)be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
}
else if (version == 1)
{
diff --git a/src/backend/sql/gnc-recurrence-sql.cpp b/src/backend/sql/gnc-recurrence-sql.cpp
index 7ca09ca..cb79b69 100644
--- a/src/backend/sql/gnc-recurrence-sql.cpp
+++ b/src/backend/sql/gnc-recurrence-sql.cpp
@@ -323,7 +323,7 @@ gnc_sql_set_recurrences_from_db (GncSqlBackend* be, const GncGUID* guid)
guid_buf);
auto stmt = be->create_statement_from_sql (buf);
g_free (buf);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
return result;
}
@@ -377,8 +377,8 @@ static void
upgrade_recurrence_table_1_2 (GncSqlBackend* be)
{
/* Step 1: add field, but allow it to be null */
- gboolean ok = gnc_sql_add_columns_to_table (be, TABLE_NAME,
- weekend_adjust_col_table);
+ gboolean ok = be->add_columns_to_table(TABLE_NAME,
+ weekend_adjust_col_table);
if (!ok)
{
PERR ("Unable to add recurrence_weekend_adjust column\n");
@@ -410,10 +410,10 @@ GncSqlRecurrenceBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
- (void)gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ (void)be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
}
else if (version < TABLE_VERSION)
{
diff --git a/src/backend/sql/gnc-schedxaction-sql.cpp b/src/backend/sql/gnc-schedxaction-sql.cpp
index 82c6cac..53e7694 100644
--- a/src/backend/sql/gnc-schedxaction-sql.cpp
+++ b/src/backend/sql/gnc-schedxaction-sql.cpp
@@ -125,7 +125,7 @@ GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, SCHEDXACTION_TABLE);
if (stmt == NULL) return;
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
SchedXactions* sxes;
InstanceVec instances;
sxes = gnc_book_get_schedxactions (be->book());
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index 6c60628..195777b 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -741,11 +741,11 @@ gnc_sql_slots_delete (GncSqlBackend* be, const GncGUID* guid)
buf = g_strdup_printf ("SELECT * FROM %s WHERE obj_guid='%s' and slot_type in ('%d', '%d') and not guid_val is null",
TABLE_NAME, guid_buf, KvpValue::Type::FRAME, KvpValue::Type::GLIST);
- auto stmt = gnc_sql_create_statement_from_sql (be, buf);
+ auto stmt = be->create_statement_from_sql(buf);
g_free (buf);
if (stmt != nullptr)
{
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
for (auto row : *result)
{
try
@@ -824,7 +824,6 @@ gnc_sql_slots_load (GncSqlBackend* be, QofInstance* inst)
static void
slots_load_info (slot_info_t* pInfo)
{
- gchar* buf;
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
g_return_if_fail (pInfo != NULL);
@@ -834,13 +833,13 @@ slots_load_info (slot_info_t* pInfo)
(void)guid_to_string_buff (pInfo->guid, guid_buf);
- buf = g_strdup_printf ("SELECT * FROM %s WHERE obj_guid='%s'",
- TABLE_NAME, guid_buf);
- auto stmt = gnc_sql_create_statement_from_sql (pInfo->be, buf);
- g_free (buf);
+ std::stringstream buf;
+ buf << "SELECT * FROM " << TABLE_NAME <<
+ " WHERE obj_guid='" << guid_buf << "'";
+ auto stmt = pInfo->be->create_statement_from_sql (buf.str());
if (stmt != nullptr)
{
- auto result = gnc_sql_execute_select_statement (pInfo->be, stmt);
+ auto result = pInfo->be->execute_select_statement (stmt);
for (auto row : *result)
load_slot (pInfo, row);
}
@@ -976,7 +975,7 @@ void gnc_sql_slots_load_for_sql_subquery (GncSqlBackend* be,
subquery);
// Execute the query and load the slots
- auto stmt = gnc_sql_create_statement_from_sql (be, sql);
+ auto stmt = be->create_statement_from_sql(sql);
if (stmt == nullptr)
{
PERR ("stmt == NULL, SQL = '%s'\n", sql);
@@ -984,7 +983,7 @@ void gnc_sql_slots_load_for_sql_subquery (GncSqlBackend* be,
return;
}
g_free (sql);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
for (auto row : *result)
load_slot_for_book_object (be, row, lookup_fn);
}
@@ -998,13 +997,13 @@ GncSqlSlotsBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TABLE_NAME);
+ version = be->get_table_version( TABLE_NAME);
if (version == 0)
{
- (void)gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
+ (void)be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
- ok = gnc_sql_create_index (be, "slots_guid_index", TABLE_NAME,
- obj_guid_col_table);
+ ok = be->create_index ("slots_guid_index", TABLE_NAME,
+ obj_guid_col_table);
if (!ok)
{
PERR ("Unable to create index\n");
@@ -1019,8 +1018,8 @@ GncSqlSlotsBackend::create_tables (GncSqlBackend* be)
if (version == 1)
{
gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
- ok = gnc_sql_create_index (be, "slots_guid_index", TABLE_NAME,
- obj_guid_col_table);
+ ok = be->create_index ("slots_guid_index", TABLE_NAME,
+ obj_guid_col_table);
if (!ok)
{
PERR ("Unable to create index\n");
@@ -1028,7 +1027,7 @@ GncSqlSlotsBackend::create_tables (GncSqlBackend* be)
}
else if (version == 2)
{
- ok = gnc_sql_add_columns_to_table (be, TABLE_NAME, gdate_col_table);
+ ok = be->add_columns_to_table(TABLE_NAME, gdate_col_table);
if (!ok)
{
PERR ("Unable to add gdate column\n");
diff --git a/src/backend/sql/gnc-tax-table-sql.cpp b/src/backend/sql/gnc-tax-table-sql.cpp
index 94d1f48..eca590e 100644
--- a/src/backend/sql/gnc-tax-table-sql.cpp
+++ b/src/backend/sql/gnc-tax-table-sql.cpp
@@ -239,7 +239,7 @@ load_taxtable_entries (GncSqlBackend* be, GncTaxTable* tt)
TTENTRIES_TABLE_NAME, guid_buf);
auto stmt = be->create_statement_from_sql (buf);
g_free (buf);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
for (auto row : *result)
load_single_ttentry (be, row, tt);
}
@@ -295,7 +295,7 @@ GncSqlTaxTableBackend::load_all (GncSqlBackend* be)
/* First time, create the query */
auto stmt = gnc_sql_create_select_statement (be, TT_TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
GList* tt_needing_parents = NULL;
for (auto row : *result)
@@ -333,10 +333,10 @@ GncSqlTaxTableBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TT_TABLE_NAME);
+ version = be->get_table_version( TT_TABLE_NAME);
if (version == 0)
{
- gnc_sql_create_table (be, TT_TABLE_NAME, TT_TABLE_VERSION, tt_col_table);
+ be->create_table(TT_TABLE_NAME, TT_TABLE_VERSION, tt_col_table);
}
else if (version == 1)
{
@@ -347,10 +347,10 @@ GncSqlTaxTableBackend::create_tables (GncSqlBackend* be)
TT_TABLE_VERSION);
}
- version = gnc_sql_get_table_version (be, TTENTRIES_TABLE_NAME);
+ version = be->get_table_version( TTENTRIES_TABLE_NAME);
if (version == 0)
{
- gnc_sql_create_table (be, TTENTRIES_TABLE_NAME, TTENTRIES_TABLE_VERSION,
+ be->create_table(TTENTRIES_TABLE_NAME, TTENTRIES_TABLE_VERSION,
ttentries_col_table);
}
else if (version == 1)
diff --git a/src/backend/sql/gnc-transaction-sql.cpp b/src/backend/sql/gnc-transaction-sql.cpp
index a5f6334..74ddd1b 100644
--- a/src/backend/sql/gnc-transaction-sql.cpp
+++ b/src/backend/sql/gnc-transaction-sql.cpp
@@ -351,7 +351,7 @@ query_transactions (GncSqlBackend* be, const GncSqlStatementPtr& stmt)
g_return_if_fail (be != NULL);
g_return_if_fail (stmt != NULL);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
if (result->begin() == result->end())
return;
@@ -474,12 +474,12 @@ GncSqlTransBackend::create_tables (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, m_table_name.c_str());
+ version = be->get_table_version( m_table_name.c_str());
if (version == 0)
{
- (void)gnc_sql_create_table (be, TRANSACTION_TABLE, TX_TABLE_VERSION,
+ (void)be->create_table(TRANSACTION_TABLE, TX_TABLE_VERSION,
tx_col_table);
- ok = gnc_sql_create_index (be, "tx_post_date_index", TRANSACTION_TABLE,
+ ok = be->create_index ("tx_post_date_index", TRANSACTION_TABLE,
post_date_col_table);
if (!ok)
{
@@ -503,15 +503,15 @@ GncSqlSplitBackend::create_tables (GncSqlBackend* be)
{
g_return_if_fail (be != nullptr);
- auto version = gnc_sql_get_table_version (be, m_table_name.c_str());
+ auto version = be->get_table_version( m_table_name.c_str());
if (version == 0)
{
- (void)gnc_sql_create_table (be, m_table_name.c_str(),
+ (void)be->create_table(m_table_name.c_str(),
m_version, m_col_table);
- if (!gnc_sql_create_index (be, "splits_tx_guid_index",
+ if (!be->create_index("splits_tx_guid_index",
m_table_name.c_str(), tx_guid_col_table))
PERR ("Unable to create index\n");
- if (!gnc_sql_create_index (be, "splits_account_guid_index",
+ if (!be->create_index("splits_account_guid_index",
m_table_name.c_str(),
account_guid_col_table))
PERR ("Unable to create index\n");
@@ -523,11 +523,11 @@ GncSqlSplitBackend::create_tables (GncSqlBackend* be)
1->2: 64 bit int handling
3->4: Split reconcile date can be NULL */
gnc_sql_upgrade_table (be, m_table_name.c_str(), split_col_table);
- if (!gnc_sql_create_index (be, "splits_tx_guid_index",
+ if (!be->create_index("splits_tx_guid_index",
m_table_name.c_str(),
tx_guid_col_table))
PERR ("Unable to create index\n");
- if (!gnc_sql_create_index (be, "splits_account_guid_index",
+ if (!be->create_index("splits_account_guid_index",
m_table_name.c_str(),
account_guid_col_table))
PERR ("Unable to create index\n");
@@ -761,7 +761,7 @@ void gnc_sql_transaction_load_tx_for_account (GncSqlBackend* be,
query_sql = g_strdup_printf (
"SELECT DISTINCT t.* FROM %s AS t, %s AS s WHERE s.tx_guid=t.guid AND s.account_guid ='%s'",
TRANSACTION_TABLE, SPLIT_TABLE, guid_buf);
- auto stmt = gnc_sql_create_statement_from_sql (be, query_sql);
+ auto stmt = be->create_statement_from_sql(query_sql);
g_free (query_sql);
if (stmt != nullptr)
{
@@ -781,7 +781,7 @@ GncSqlTransBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
- auto stmt = gnc_sql_create_statement_from_sql (be, query_sql);
+ auto stmt = be->create_statement_from_sql(query_sql);
g_free (query_sql);
if (stmt != nullptr)
{
@@ -1166,7 +1166,7 @@ done_compiling_query:
{
query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
}
- query_info->stmt = gnc_sql_create_statement_from_sql (be, query_sql);
+ query_info->stmt = be->create_statement_from_sql(query_sql);
g_string_free (sql, TRUE);
g_free (query_sql);
@@ -1175,7 +1175,7 @@ done_compiling_query:
else
{
query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
- query_info->stmt = gnc_sql_create_statement_from_sql (be, query_sql);
+ query_info->stmt = be->create_statement_from_sql(query_sql);
g_free (query_sql);
}
@@ -1287,10 +1287,10 @@ gnc_sql_get_account_balances_slist (GncSqlBackend* be)
buf = g_strdup_printf ("SELECT account_guid, reconcile_state, sum(quantity_num) as quantity_num, quantity_denom FROM %s GROUP BY account_guid, reconcile_state, quantity_denom ORDER BY account_guid, reconcile_state",
SPLIT_TABLE);
- auto stmt = gnc_sql_create_statement_from_sql (be, buf);
+ auto stmt = be->create_statement_from_sql(buf);
g_assert (stmt != nullptr);
g_free (buf);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
acct_balances_t* bal = NULL;
for (auto row : *result)
@@ -1383,8 +1383,7 @@ GncSqlColumnTableEntryImpl<CT_TXREF>::load (const GncSqlBackend* be,
{
auto buf = std::string{"SELECT * FROM "} + TRANSACTION_TABLE +
" WHERE guid='" + val + "'";
- auto stmt = gnc_sql_create_statement_from_sql ((GncSqlBackend*)be,
- buf.c_str());
+ auto stmt = be->create_statement_from_sql (buf);
query_transactions ((GncSqlBackend*)be, stmt);
tx = xaccTransLookup (&guid, be->book());
}
diff --git a/src/backend/sql/gnc-vendor-sql.cpp b/src/backend/sql/gnc-vendor-sql.cpp
index 37d3070..5aaa56b 100644
--- a/src/backend/sql/gnc-vendor-sql.cpp
+++ b/src/backend/sql/gnc-vendor-sql.cpp
@@ -116,7 +116,7 @@ GncSqlVendorBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement(stmt);
InstanceVec instances;
for (auto row : *result)
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index c31070a..27d3817 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -828,13 +828,6 @@ do_create_table (const GncSqlBackend* be, const gchar* table_name,// 5
test_do_create_table (Fixture *fixture, gconstpointer pData)
{
}*/
-/* gnc_sql_create_table
-gboolean
-gnc_sql_create_table (GncSqlBackend* be, const gchar* table_name,// C: 22 in 19 */
-/* static void
-test_gnc_sql_create_table (Fixture *fixture, gconstpointer pData)
-{
-}*/
// Make Static
/* gnc_sql_create_temp_table
gboolean
@@ -851,13 +844,6 @@ gnc_sql_create_index (const GncSqlBackend* be, const gchar* index_name,// C: 7 i
test_gnc_sql_create_index (Fixture *fixture, gconstpointer pData)
{
}*/
-/* gnc_sql_get_table_version
-gint
-gnc_sql_get_table_version (const GncSqlBackend* be, const gchar* table_name)// C: 24 in 20 */
-/* static void
-test_gnc_sql_get_table_version (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* gnc_sql_upgrade_table
void
gnc_sql_upgrade_table (GncSqlBackend* be, const gchar* table_name,// C: 12 in 10 */
@@ -893,14 +879,6 @@ gnc_sql_finalize_version_info (GncSqlBackend* be)// C: 1 */
test_gnc_sql_finalize_version_info (Fixture *fixture, gconstpointer pData)
{
}*/
-/* gnc_sql_set_table_version
-gboolean
-gnc_sql_set_table_version (GncSqlBackend* be, const gchar* table_name, gint version)// C: 12 in 10 */
-/* static void
-test_gnc_sql_set_table_version (Fixture *fixture, gconstpointer pData)
-{
-}*/
-
void
test_suite_gnc_backend_sql (void)
@@ -992,15 +970,12 @@ test_suite_gnc_backend_sql (void)
// GNC_TEST_ADD (suitename, "build update statement", Fixture, nullptr, test_build_update_statement, teardown);
// GNC_TEST_ADD (suitename, "build delete statement", Fixture, nullptr, test_build_delete_statement, teardown);
// GNC_TEST_ADD (suitename, "do create table", Fixture, nullptr, test_do_create_table, teardown);
-// GNC_TEST_ADD (suitename, "gnc sql create table", Fixture, nullptr, test_gnc_sql_create_table, teardown);
// GNC_TEST_ADD (suitename, "gnc sql create temp table", Fixture, nullptr, test_gnc_sql_create_temp_table, teardown);
// GNC_TEST_ADD (suitename, "gnc sql create index", Fixture, nullptr, test_gnc_sql_create_index, teardown);
-// GNC_TEST_ADD (suitename, "gnc sql get table version", Fixture, nullptr, test_gnc_sql_get_table_version, teardown);
// GNC_TEST_ADD (suitename, "gnc sql upgrade table", Fixture, nullptr, test_gnc_sql_upgrade_table, teardown);
// GNC_TEST_ADD (suitename, "gnc sql add columns to table", Fixture, nullptr, test_gnc_sql_add_columns_to_table, teardown);
// GNC_TEST_ADD (suitename, "gnc sql init version info", Fixture, nullptr, test_gnc_sql_init_version_info, teardown);
// GNC_TEST_ADD (suitename, "reset version info", Fixture, nullptr, test_reset_version_info, teardown);
// GNC_TEST_ADD (suitename, "gnc sql finalize version info", Fixture, nullptr, test_gnc_sql_finalize_version_info, teardown);
-// GNC_TEST_ADD (suitename, "gnc sql set table version", Fixture, nullptr, test_gnc_sql_set_table_version, teardown);
}
commit a303ae688afae1a972ad91a4aa4ea7cfdf6f79e6
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Jul 24 10:40:09 2016 -0700
Remove some GList and GSList uses from tests.
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index 86b1678..fabc26f 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -523,7 +523,7 @@ GncDbiSqlConnection::table_manage_backup (const std::string& table_name,
*
* @param sql_conn: The sql connection (via dbi) to which the
* transactions will be sent
- * @param tables: GList of tables to operate on.
+ * @param table_namess: StrVec of tables to operate on.
* @param op: The operation to perform.
* @return Success (TRUE) or failure.
*/
diff --git a/src/backend/dbi/test/test-backend-dbi-basic.cpp b/src/backend/dbi/test/test-backend-dbi-basic.cpp
index 7d57e4b..816881f 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.cpp
+++ b/src/backend/dbi/test/test-backend-dbi-basic.cpp
@@ -236,16 +236,6 @@ setup_business (Fixture* fixture, gconstpointer pData)
}
static void
-drop_table (gconstpointer tdata, gconstpointer cdata)
-{
- gchar* table = (gchar*)tdata;
- dbi_conn conn = (dbi_conn)cdata;
- gchar* query = g_strdup_printf ("DROP TABLE %s", table);
- dbi_result rslt = dbi_conn_query (conn, query);
- g_free (query);
-}
-
-static void
destroy_database (gchar* url)
{
gchar* protocol = NULL;
@@ -261,7 +251,7 @@ destroy_database (gchar* url)
auto errfmt = "Unable to delete tables in %s: %s";
gint fail = 0;
dbi_result tables;
- GSList* list = NULL;
+ StrVec tblnames;
gnc_uri_get_components (url, &protocol, &host, &portnum,
&username, &password, &dbname);
@@ -313,12 +303,16 @@ destroy_database (gchar* url)
tables = dbi_conn_get_table_list (conn, dbname, NULL);
while (dbi_result_next_row (tables) != 0)
{
- const gchar* table = dbi_result_get_string_idx (tables, 1);
- list = g_slist_prepend (list, g_strdup (table));
+ const std::string table{dbi_result_get_string_idx (tables, 1)};
+ tblnames.push_back(table);
}
dbi_result_free (tables);
- g_slist_foreach (list, (GFunc)drop_table, (gpointer)conn);
- g_slist_free_full (list, (GDestroyNotify)g_free);
+ std::for_each(tblnames.begin(), tblnames.end(),
+ [conn](std::string table) {
+ std::string query{"DROP TABLE "};
+ query += table;
+ dbi_result rslt = dbi_conn_query (conn, query.c_str());
+ });
}
static void
@@ -654,8 +648,8 @@ create_dbi_test_suite (const char* dbm_name, const char* url)
void
test_suite_gnc_backend_dbi (void)
{
- dbi_driver driver = NULL;
- GList* drivers = NULL;
+ dbi_driver driver = nullptr;
+ StrVec drivers;
#if HAVE_LIBDBI_R
if (dbi_instance == NULL)
dbi_initialize_r (NULL, &dbi_instance);
@@ -665,19 +659,19 @@ test_suite_gnc_backend_dbi (void)
while ((driver = dbi_driver_list (driver)))
#endif
{
- drivers = g_list_prepend (drivers,
- (gchar*)dbi_driver_get_name (driver));
+ drivers.push_back(dbi_driver_get_name (driver));
}
- if (g_list_find_custom (drivers, "sqlite3", (GCompareFunc)g_strcmp0))
- create_dbi_test_suite ("sqlite3", "sqlite3");
- if (strlen (TEST_MYSQL_URL) > 0 &&
- g_list_find_custom (drivers, "mysql", (GCompareFunc)g_strcmp0))
- create_dbi_test_suite ("mysql", TEST_MYSQL_URL);
- if (strlen (TEST_PGSQL_URL) > 0 &&
- g_list_find_custom (drivers, "pgsql", (GCompareFunc)g_strcmp0))
+ for (auto name : drivers)
{
- g_setenv ("PGOPTIONS", "-c client_min_messages=WARNING", FALSE);
- create_dbi_test_suite ("postgres", TEST_PGSQL_URL);
+ if (name == "sqlite3")
+ create_dbi_test_suite ("sqlite3", "sqlite3");
+ if (strlen (TEST_MYSQL_URL) > 0 && name == "mysql")
+ create_dbi_test_suite ("mysql", TEST_MYSQL_URL);
+ if (strlen (TEST_PGSQL_URL) > 0 && name == "pgsql")
+ {
+ g_setenv ("PGOPTIONS", "-c client_min_messages=WARNING", FALSE);
+ create_dbi_test_suite ("postgres", TEST_PGSQL_URL);
+ }
}
GNC_TEST_ADD_FUNC( suitename, "adjust sql options string localtime",
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index d83eb50..c31070a 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -444,23 +444,6 @@ gnc_sql_get_getter (QofIdTypeConst obj_name, const GncSqlColumnTableEntry& table
test_gnc_sql_get_getter (Fixture *fixture, gconstpointer pData)
{
}*/
-// Make Static
-/* gnc_sql_add_colname_to_list
-void
-gnc_sql_add_colname_to_list (const GncSqlColumnTableEntry& table_row, GList** pList)// 9
-*/
-/* static void
-test_gnc_sql_add_colname_to_list (Fixture *fixture, gconstpointer pData)
-{
-}*/
-/* gnc_sql_add_subtable_colnames_to_list
-void
-gnc_sql_add_subtable_colnames_to_list (const GncSqlColumnTableEntry& table_row, const EntryVec& subtable,
-GList** pList)// C: 1 */
-/* static void
-test_gnc_sql_add_subtable_colnames_to_list (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* load_string
static void
load_string (const GncSqlBackend* be, GncSqlRow& row,
@@ -470,24 +453,6 @@ const GncSqlColumnTableEntry& table_row)// 2
test_load_string (Fixture *fixture, gconstpointer pData)
{
}*/
-/* add_string_col_info_to_list
-static void
-add_string_col_info_to_list (const GncSqlBackend* be, const GncSqlColumnTableEntry& table_row,
-GList** pList)// 2
-*/
-/* static void
-test_add_string_col_info_to_list (Fixture *fixture, gconstpointer pData)
-{
-}*/
-/* add_gvalue_string_to_slist
-static void
-add_gvalue_string_to_slist (const GncSqlBackend* be, QofIdTypeConst obj_name,
-const gpointer pObject, const GncSqlColumnTableEntry& table_row, GSList** pList)// 2
-*/
-/* static void
-test_add_gvalue_string_to_slist (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* load_int
static void
load_int (const GncSqlBackend* be, GncSqlRow& row,// 4
@@ -718,14 +683,6 @@ add_numeric_col_info_to_list (const GncSqlBackend* be, const GncSqlColumnTableEn
test_add_numeric_col_info_to_list (Fixture *fixture, gconstpointer pData)
{
}*/
-/* add_numeric_colname_to_list
-static void
-add_numeric_colname_to_list (const GncSqlColumnTableEntry& table_row, GList** pList)// 2
-*/
-/* static void
-test_add_numeric_colname_to_list (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* add_value_numeric_to_vec
static void
add_value_numeric_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,// 2
@@ -818,13 +775,6 @@ execute_statement_get_count (GncSqlBackend* be, GncSqlStatement* stmt)// 2
test_execute_statement_get_count (Fixture *fixture, gconstpointer pData)
{
}*/
-/* gnc_sql_append_guid_list_to_sql
-guint
-gnc_sql_append_guid_list_to_sql (GString* sql, GList* list, guint maxCount)// C: 2 in 2 */
-/* static void
-test_gnc_sql_append_guid_list_to_sql (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* gnc_sql_object_is_it_in_db
gboolean
gnc_sql_object_is_it_in_db (GncSqlBackend* be, const gchar* table_name,// C: 1 */
@@ -839,14 +789,6 @@ gnc_sql_do_db_operation (GncSqlBackend* be,// C: 22 in 12 */
test_gnc_sql_do_db_operation (Fixture *fixture, gconstpointer pData)
{
}*/
-/* create_gslist_from_values
-static GSList*
-create_gslist_from_values (GncSqlBackend* be,// 3
-*/
-/* static void
-test_create_gslist_from_values (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* gnc_sql_get_sql_value
gchar*
gnc_sql_get_sql_value (const GncSqlConnection* conn, const GValue* value)// C: 1 */
@@ -854,14 +796,6 @@ gnc_sql_get_sql_value (const GncSqlConnection* conn, const GValue* value)// C: 1
test_gnc_sql_get_sql_value (Fixture *fixture, gconstpointer pData)
{
}*/
-/* free_gvalue_list
-static void
-free_gvalue_list (GSList* list)// 4
-*/
-/* static void
-test_free_gvalue_list (Fixture *fixture, gconstpointer pData)
-{
-}*/
// Make Static
/* build_insert_statement
build_insert_statement (GncSqlBackend* be,// 3
@@ -1004,7 +938,6 @@ test_suite_gnc_backend_sql (void)
// GNC_TEST_ADD (suitename, "get autoinc id", Fixture, nullptr, test_get_autoinc_id, teardown);
// GNC_TEST_ADD (suitename, "set autoinc id", Fixture, nullptr, test_set_autoinc_id, teardown);
// GNC_TEST_ADD (suitename, "gnc sql get getter", Fixture, nullptr, test_gnc_sql_get_getter, teardown);
-// GNC_TEST_ADD (suitename, "gnc sql add colname to list", Fixture, nullptr, test_gnc_sql_add_colname_to_list, teardown);
// GNC_TEST_ADD (suitename, "gnc sql add subtable colnames to list", Fixture, nullptr, test_gnc_sql_add_subtable_colnames_to_list, teardown);
// GNC_TEST_ADD (suitename, "load string", Fixture, nullptr, test_load_string, teardown);
// GNC_TEST_ADD (suitename, "add string col info to list", Fixture, nullptr, test_add_string_col_info_to_list, teardown);
@@ -1054,9 +987,7 @@ test_suite_gnc_backend_sql (void)
// GNC_TEST_ADD (suitename, "gnc sql append guid list to sql", Fixture, nullptr, test_gnc_sql_append_guid_list_to_sql, teardown);
// GNC_TEST_ADD (suitename, "gnc sql object is it in db", Fixture, nullptr, test_gnc_sql_object_is_it_in_db, teardown);
// GNC_TEST_ADD (suitename, "gnc sql do db operation", Fixture, nullptr, test_gnc_sql_do_db_operation, teardown);
-// GNC_TEST_ADD (suitename, "create gslist from values", Fixture, nullptr, test_create_gslist_from_values, teardown);
// GNC_TEST_ADD (suitename, "gnc sql get sql value", Fixture, nullptr, test_gnc_sql_get_sql_value, teardown);
-// GNC_TEST_ADD (suitename, "free gvalue list", Fixture, nullptr, test_free_gvalue_list, teardown);
// GNC_TEST_ADD (suitename, "build insert statement", Fixture, nullptr, test_build_insert_statement, teardown);
// GNC_TEST_ADD (suitename, "build update statement", Fixture, nullptr, test_build_update_statement, teardown);
// GNC_TEST_ADD (suitename, "build delete statement", Fixture, nullptr, test_build_delete_statement, teardown);
commit 4b62deee42db1734922bb255d3d86e1883f9271e
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Jul 24 10:39:14 2016 -0700
Rework gnc_sql_append_guid_list_to_sql to eliminate GString and GList.
Which in turn forced rework of its users since the GString and GList were
passed-in parameters.
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index 39670d8..7d61beb 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -625,7 +625,7 @@ GncSqlBackend::get_table_version(const std::string& table_name) const noexcept
*/
bool
GncSqlBackend::set_table_version (const std::string& table_name,
- unsigned int version) noexcept
+ uint_t version) noexcept
{
g_return_val_if_fail (version > 0, false);
@@ -2069,33 +2069,23 @@ gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql)
return be->execute_nonselect_statement (stmt);
}
-guint
-gnc_sql_append_guid_list_to_sql (GString* sql, GList* list, guint maxCount)
+uint_t
+gnc_sql_append_guids_to_sql (std::stringstream& sql, const InstanceVec& instances)
{
- gchar guid_buf[GUID_ENCODING_LENGTH + 1];
- gboolean first_guid = TRUE;
- guint count;
-
- g_return_val_if_fail (sql != NULL, 0);
+ char guid_buf[GUID_ENCODING_LENGTH + 1];
- if (list == NULL) return 0;
-
- for (count = 0; list != NULL && count < maxCount; list = list->next, count++)
+ for (auto inst : instances)
{
- QofInstance* inst = QOF_INSTANCE (list->data);
(void)guid_to_string_buff (qof_instance_get_guid (inst), guid_buf);
- if (!first_guid)
+ if (inst != *(instances.begin()))
{
- (void)g_string_append (sql, ",");
+ sql << ",";
}
- (void)g_string_append (sql, "'");
- (void)g_string_append (sql, guid_buf);
- (void)g_string_append (sql, "'");
- first_guid = FALSE;
+ sql << "'" << guid_buf << "'";
}
- return count;
+ return instances.size();
}
/* ================================================================= */
static PairVec
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 35c3220..10227c4 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -50,13 +50,17 @@ extern "C"
#include <string>
#include <vector>
#include <memory>
+#include <cstdint>
+
+using uint_t = unsigned int;
struct GncSqlColumnInfo;
class GncSqlColumnTableEntry;
using GncSqlColumnTableEntryPtr = std::shared_ptr<GncSqlColumnTableEntry>;
using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
using ColVec = std::vector<GncSqlColumnInfo>;
using StrVec = std::vector<std::string>;
+using InstanceVec = std::vector<QofInstance*>;
using PairVec = std::vector<std::pair<std::string, std::string>>;
using VersionPair = std::pair<const std::string, unsigned int>;
using VersionVec = std::vector<VersionPair>;
@@ -98,7 +102,7 @@ public:
bool add_columns_to_table(const std::string& table_name,
const EntryVec& col_table) const noexcept;
unsigned int get_table_version(const std::string& table_name) const noexcept;
- bool set_table_version (const std::string& table_name, unsigned int version) noexcept;
+ bool set_table_version (const std::string& table_name, uint_t version) noexcept;
QofBook* book() const noexcept { return m_book; }
bool pristine() const noexcept { return m_is_pristine_db; }
@@ -946,8 +950,8 @@ GncSqlStatementPtr gnc_sql_create_select_statement (GncSqlBackend* be,
* @param maxCount Max # of GUIDs to append
* @return Number of GUIDs appended
*/
-guint gnc_sql_append_guid_list_to_sql (GString* str, GList* list,
- guint maxCount);
+uint_t gnc_sql_append_guids_to_sql (std::stringstream& sql,
+ const InstanceVec& instances);
/**
* Initializes DB table version information.
diff --git a/src/backend/sql/gnc-bill-term-sql.cpp b/src/backend/sql/gnc-bill-term-sql.cpp
index e4054d7..9b41b76 100644
--- a/src/backend/sql/gnc-bill-term-sql.cpp
+++ b/src/backend/sql/gnc-bill-term-sql.cpp
@@ -240,22 +240,19 @@ GncSqlBillTermBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- GList* list = NULL;
+ InstanceVec instances;
GList* l_billterms_needing_parents = NULL;
for (auto row : *result)
{
auto pBillTerm =
load_single_billterm (be, row, &l_billterms_needing_parents);
- if (pBillTerm != NULL)
- list = g_list_append (list, pBillTerm);
+ if (pBillTerm != nullptr)
+ instances.push_back(QOF_INSTANCE(pBillTerm));
}
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
/* While there are items on the list of billterms needing parents,
try to see if the parent has now been loaded. Theory says that if
diff --git a/src/backend/sql/gnc-budget-sql.cpp b/src/backend/sql/gnc-budget-sql.cpp
index 96aee9f..ddf05bd 100644
--- a/src/backend/sql/gnc-budget-sql.cpp
+++ b/src/backend/sql/gnc-budget-sql.cpp
@@ -332,29 +332,23 @@ load_single_budget (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlBudgetBackend::load_all (GncSqlBackend* be)
{
- GList* list = NULL;
-
+ InstanceVec instances;
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, BUDGET_TABLE);
- if (stmt != nullptr)
- {
- auto result = gnc_sql_execute_select_statement (be, stmt);
- for (auto row : *result)
- {
- auto b = load_single_budget (be, row);
- if (b != NULL)
- {
- list = g_list_prepend (list, b);
- }
- }
+ if (stmt == nullptr)
+ return;
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ auto result = gnc_sql_execute_select_statement (be, stmt);
+ for (auto row : *result)
+ {
+ auto b = load_single_budget (be, row);
+ if (b != nullptr)
+ instances.push_back(QOF_INSTANCE(b));
}
+
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */
diff --git a/src/backend/sql/gnc-customer-sql.cpp b/src/backend/sql/gnc-customer-sql.cpp
index de77b24..91e3c49 100644
--- a/src/backend/sql/gnc-customer-sql.cpp
+++ b/src/backend/sql/gnc-customer-sql.cpp
@@ -126,25 +126,19 @@ GncSqlCustomerBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
-
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- GList* list = NULL;
+ InstanceVec instances;
for (auto row : *result)
{
GncCustomer* pCustomer = load_single_customer (be, row);
- if (pCustomer != NULL)
- {
- list = g_list_append (list, pCustomer);
- }
+ if (pCustomer != nullptr)
+ instances.push_back(QOF_INSTANCE(pCustomer));
}
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */
diff --git a/src/backend/sql/gnc-employee-sql.cpp b/src/backend/sql/gnc-employee-sql.cpp
index f295a5d..a39e2ce 100644
--- a/src/backend/sql/gnc-employee-sql.cpp
+++ b/src/backend/sql/gnc-employee-sql.cpp
@@ -115,23 +115,17 @@ GncSqlEmployeeBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- GList* list = NULL;
+ InstanceVec instances;
for (auto row : *result)
{
GncEmployee* pEmployee = load_single_employee (be, row);
- if (pEmployee != NULL)
- {
- list = g_list_append (list, pEmployee);
- }
- }
-
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
+ if (pEmployee != nullptr)
+ instances.push_back(QOF_INSTANCE(pEmployee));
}
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */
diff --git a/src/backend/sql/gnc-entry-sql.cpp b/src/backend/sql/gnc-entry-sql.cpp
index 3f0623d..f6d31ed 100644
--- a/src/backend/sql/gnc-entry-sql.cpp
+++ b/src/backend/sql/gnc-entry-sql.cpp
@@ -196,22 +196,17 @@ GncSqlEntryBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- GList* list = NULL;
+ InstanceVec instances;
for (auto row : *result)
{
GncEntry* pEntry = load_single_entry (be, row);
- if (pEntry != NULL)
- {
- list = g_list_append (list, pEntry);
- }
+ if (pEntry != nullptr)
+ instances.push_back(QOF_INSTANCE(pEntry));
}
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec(be, instances);
}
/* ================================================================= */
diff --git a/src/backend/sql/gnc-invoice-sql.cpp b/src/backend/sql/gnc-invoice-sql.cpp
index d6d8f5d..f1c14b2 100644
--- a/src/backend/sql/gnc-invoice-sql.cpp
+++ b/src/backend/sql/gnc-invoice-sql.cpp
@@ -135,22 +135,17 @@ GncSqlInvoiceBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- GList* list = NULL;
+ InstanceVec instances;
for (auto row : *result)
{
GncInvoice* pInvoice = load_single_invoice (be, row);
- if (pInvoice != NULL)
- {
- list = g_list_append (list, pInvoice);
- }
+ if (pInvoice != nullptr)
+ instances.push_back(QOF_INSTANCE(pInvoice));
}
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */
diff --git a/src/backend/sql/gnc-job-sql.cpp b/src/backend/sql/gnc-job-sql.cpp
index cb03233..019c306 100644
--- a/src/backend/sql/gnc-job-sql.cpp
+++ b/src/backend/sql/gnc-job-sql.cpp
@@ -107,22 +107,17 @@ GncSqlJobBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- GList* list = NULL;
+ InstanceVec instances;
for (auto row : *result)
{
GncJob* pJob = load_single_job (be, row);
- if (pJob != NULL)
- {
- list = g_list_append (list, pJob);
- }
+ if (pJob != nullptr)
+ instances.push_back(QOF_INSTANCE(pJob));
}
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */
diff --git a/src/backend/sql/gnc-order-sql.cpp b/src/backend/sql/gnc-order-sql.cpp
index 8541bbe..7115f25 100644
--- a/src/backend/sql/gnc-order-sql.cpp
+++ b/src/backend/sql/gnc-order-sql.cpp
@@ -107,22 +107,17 @@ GncSqlOrderBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- GList* list = NULL;
+ InstanceVec instances;
for (auto row : *result)
{
GncOrder* pOrder = load_single_order (be, row);
- if (pOrder != NULL)
- {
- list = g_list_append (list, pOrder);
- }
+ if (pOrder != nullptr)
+ instances.push_back(QOF_INSTANCE(pOrder));
}
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */
diff --git a/src/backend/sql/gnc-schedxaction-sql.cpp b/src/backend/sql/gnc-schedxaction-sql.cpp
index 3eb6e3c..82c6cac 100644
--- a/src/backend/sql/gnc-schedxaction-sql.cpp
+++ b/src/backend/sql/gnc-schedxaction-sql.cpp
@@ -127,7 +127,7 @@ GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
if (stmt == NULL) return;
auto result = gnc_sql_execute_select_statement (be, stmt);
SchedXactions* sxes;
- GList* list = NULL;
+ InstanceVec instances;
sxes = gnc_book_get_schedxactions (be->book());
for (auto row : *result)
@@ -135,18 +135,15 @@ GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
SchedXaction* sx;
sx = load_single_sx (be, row);
- if (sx != NULL)
+ if (sx != nullptr)
{
gnc_sxes_add_sx (sxes, sx);
- list = g_list_prepend (list, sx);
+ instances.push_back(QOF_INSTANCE(sx));
}
}
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index c91f77c..6c60628 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -886,50 +886,39 @@ load_slot_for_list_item (GncSqlBackend* be, GncSqlRow& row,
}
void
-gnc_sql_slots_load_for_list (GncSqlBackend* be, GList* list)
+gnc_sql_slots_load_for_instancevec (GncSqlBackend* be, InstanceVec& instances)
{
QofCollection* coll;
- GString* sql;
- gboolean single_item;
+ std::stringstream sql;
g_return_if_fail (be != NULL);
// Ignore empty list
- if (list == NULL) return;
+ if (instances.empty()) return;
- coll = qof_instance_get_collection (QOF_INSTANCE (list->data));
+ coll = qof_instance_get_collection (instances[0]);
// Create the query for all slots for all items on the list
- sql = g_string_sized_new (40 + (GUID_ENCODING_LENGTH + 3) * g_list_length (
- list));
- g_string_append_printf (sql, "SELECT * FROM %s WHERE %s ", TABLE_NAME,
- obj_guid_col_table[0]->name());
- if (g_list_length (list) != 1)
- {
- (void)g_string_append (sql, "IN (");
- single_item = FALSE;
- }
+
+ sql << "SELECT * FROM " << TABLE_NAME << " WHERE " <<
+ obj_guid_col_table[0]->name();
+ if (instances.size() != 1)
+ sql << " IN (";
else
- {
- (void)g_string_append (sql, "= ");
- single_item = TRUE;
- }
- (void)gnc_sql_append_guid_list_to_sql (sql, list, G_MAXUINT);
- if (!single_item)
- {
- (void)g_string_append (sql, ")");
- }
+ sql << " = ";
+
+ gnc_sql_append_guids_to_sql (sql, instances);
+ if (instances.size() > 1)
+ sql << ")";
// Execute the query and load the slots
- auto stmt = gnc_sql_create_statement_from_sql (be, sql->str);
+ auto stmt = be->create_statement_from_sql(sql.str());
if (stmt == nullptr)
{
- PERR ("stmt == NULL, SQL = '%s'\n", sql->str);
- (void)g_string_free (sql, TRUE);
+ PERR ("stmt == NULL, SQL = '%s'\n", sql.str().c_str());
return;
}
- (void)g_string_free (sql, TRUE);
- auto result = gnc_sql_execute_select_statement (be, stmt);
+ auto result = be->execute_select_statement (stmt);
for (auto row : *result)
load_slot_for_list_item (be, row, coll);
}
diff --git a/src/backend/sql/gnc-slots-sql.h b/src/backend/sql/gnc-slots-sql.h
index 6690777..e931eda 100644
--- a/src/backend/sql/gnc-slots-sql.h
+++ b/src/backend/sql/gnc-slots-sql.h
@@ -64,14 +64,15 @@ gboolean gnc_sql_slots_delete (GncSqlBackend* be, const GncGUID* guid);
void gnc_sql_slots_load (GncSqlBackend* be, QofInstance* inst);
/**
- * gnc_sql_slots_load_for_list - Loads slots for a list of objects from the db.
- * Loading slots for a list of objects can be faster than loading for one object
+ * gnc_sql_slots_load_for_instancevec - Loads slots for a set of QofInstance*
+ * from the db. Loading slots for a set is faster than loading for one object
* at a time because fewer SQL queries are used.
*
* @param be SQL backend
* @param list List of objects
*/
-void gnc_sql_slots_load_for_list (GncSqlBackend* be, GList* list);
+void gnc_sql_slots_load_for_instancevec (GncSqlBackend* be,
+ InstanceVec& instances);
typedef QofInstance* (*BookLookupFn) (const GncGUID* guid,
const QofBook* book);
diff --git a/src/backend/sql/gnc-transaction-sql.cpp b/src/backend/sql/gnc-transaction-sql.cpp
index e1300ad..a5f6334 100644
--- a/src/backend/sql/gnc-transaction-sql.cpp
+++ b/src/backend/sql/gnc-transaction-sql.cpp
@@ -258,40 +258,31 @@ load_single_split (GncSqlBackend* be, GncSqlRow& row)
}
static void
-load_splits_for_tx_list (GncSqlBackend* be, GList* list)
+load_splits_for_tx_list (GncSqlBackend* be, InstanceVec& transactions)
{
- GString* sql;
-
g_return_if_fail (be != NULL);
- if (list == NULL) return;
+ std::stringstream sql;
- sql = g_string_sized_new (40 + (GUID_ENCODING_LENGTH + 3) * g_list_length (
- list));
- g_string_append_printf (sql, "SELECT * FROM %s WHERE %s IN (", SPLIT_TABLE,
- tx_guid_col_table[0]->name());
- (void)gnc_sql_append_guid_list_to_sql (sql, list, G_MAXUINT);
- (void)g_string_append (sql, ")");
+ sql << "SELECT * FROM " << SPLIT_TABLE << " WHERE " <<
+ tx_guid_col_table[0]->name() << " IN (";
+ gnc_sql_append_guids_to_sql (sql, transactions);
+ sql << ")";
// Execute the query and load the splits
- auto result = gnc_sql_execute_select_sql (be, sql->str);
- GList* split_list = NULL;
+ auto stmt = be->create_statement_from_sql(sql.str());
+ auto result = be->execute_select_statement (stmt);
+ InstanceVec instances;
+
for (auto row : *result)
{
- Split* s;
- s = load_single_split (be, row);
- if (s != NULL)
- {
- split_list = g_list_prepend (split_list, s);
- }
+ Split* s = load_single_split (be, row);
+ if (s != nullptr)
+ instances.push_back(QOF_INSTANCE(s));
}
- if (split_list != NULL)
- {
- gnc_sql_slots_load_for_list (be, split_list);
- g_list_free (split_list);
- }
- (void)g_string_free (sql, TRUE);
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
static Transaction*
@@ -364,7 +355,6 @@ query_transactions (GncSqlBackend* be, const GncSqlStatementPtr& stmt)
if (result->begin() == result->end())
return;
- GList* tx_list = NULL;
GList* node;
Transaction* tx;
#if LOAD_TRANSACTIONS_AS_NEEDED
@@ -383,30 +373,27 @@ query_transactions (GncSqlBackend* be, const GncSqlStatementPtr& stmt)
#endif
// Load the transactions
+ InstanceVec instances;
for (auto row : *result)
{
tx = load_single_tx (be, row);
- if (tx != NULL)
+ if (tx != nullptr)
{
xaccTransScrubPostedDate (tx);
- tx_list = g_list_prepend (tx_list, tx);
+ instances.push_back(QOF_INSTANCE(tx));
}
}
// Load all splits and slots for the transactions
- if (tx_list != NULL)
+ if (!instances.empty())
{
- gnc_sql_slots_load_for_list (be, tx_list);
- load_splits_for_tx_list (be, tx_list);
+ gnc_sql_slots_load_for_instancevec (be, instances);
+ load_splits_for_tx_list (be, instances);
}
// Commit all of the transactions
- for (node = tx_list; node != NULL; node = node->next)
- {
- Transaction* pTx = GNC_TRANSACTION (node->data);
- xaccTransCommitEdit (pTx);
- }
- g_list_free (tx_list);
+ for (auto instance : instances)
+ xaccTransCommitEdit(GNC_TRANSACTION(instance));
#if LOAD_TRANSACTIONS_AS_NEEDED
// Update the account balances based on the loaded splits. If the end
diff --git a/src/backend/sql/gnc-vendor-sql.cpp b/src/backend/sql/gnc-vendor-sql.cpp
index 6ee5035..37d3070 100644
--- a/src/backend/sql/gnc-vendor-sql.cpp
+++ b/src/backend/sql/gnc-vendor-sql.cpp
@@ -117,20 +117,17 @@ GncSqlVendorBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- GList* list = NULL;
+ InstanceVec instances;
for (auto row : *result)
{
GncVendor* pVendor = load_single_vendor (be, row);
- if (pVendor != NULL)
- list = g_list_append (list, pVendor);
+ if (pVendor != nullptr)
+ instances.push_back(QOF_INSTANCE(pVendor));
}
- if (list != NULL)
- {
- gnc_sql_slots_load_for_list (be, list);
- g_list_free (list);
- }
+ if (!instances.empty())
+ gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */
commit cb464da599ec3dabead4427a3ff47b975b925317
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jul 23 14:33:34 2016 -0700
Replace GHashTable in GncSqlConnection with a std::vector.
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index b1ced87..39670d8 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -431,8 +431,7 @@ GncSqlBackend::GncSqlBackend(GncSqlConnection *conn, QofBook* book,
be {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, ERR_BACKEND_NO_ERR, nullptr, 0,
nullptr}, m_conn{conn}, m_book{book}, m_loading{false},
- m_in_query{false}, m_is_pristine_db{false}, m_versions{nullptr},
- m_timespec_format{format}
+ m_in_query{false}, m_is_pristine_db{false}, m_timespec_format{format}
{
if (conn != nullptr)
connect (conn);
@@ -443,8 +442,7 @@ GncSqlBackend::connect(GncSqlConnection *conn) noexcept
{
if (m_conn != nullptr && m_conn != conn)
delete m_conn;
- if (m_versions != nullptr)
- finalize_version_info();
+ finalize_version_info();
m_conn = conn;
}
@@ -549,11 +547,6 @@ GncSqlBackend::finish_progress() const noexcept
void
GncSqlBackend::init_version_info() noexcept
{
- if (m_versions != NULL)
- {
- g_hash_table_destroy (m_versions);
- }
- m_versions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
if (m_conn->does_table_exist (VERSION_TABLE_NAME))
{
@@ -564,9 +557,8 @@ GncSqlBackend::init_version_info() noexcept
for (const auto& row : *result)
{
auto name = row.get_string_at_col (TABLE_COL_NAME);
- auto version = row.get_int_at_col (VERSION_COL_NAME);
- g_hash_table_insert (m_versions, g_strdup (name.c_str()),
- GINT_TO_POINTER (version));
+ unsigned int version = row.get_int_at_col (VERSION_COL_NAME);
+ m_versions.push_back(std::make_pair(name, version));
}
}
else
@@ -590,15 +582,7 @@ GncSqlBackend::reset_version_info() noexcept
bool ok = true;
if (!m_conn->does_table_exist (VERSION_TABLE_NAME))
ok = create_table (VERSION_TABLE_NAME, version_table);
- if (m_versions == nullptr)
- {
- m_versions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- }
- else
- {
- g_hash_table_remove_all (m_versions);
- }
-
+ m_versions.clear();
set_table_version ("Gnucash", gnc_prefs_get_long_version ());
set_table_version ("Gnucash-Resave", GNUCASH_RESAVE_VERSION);
return ok;
@@ -612,22 +596,22 @@ GncSqlBackend::reset_version_info() noexcept
void
GncSqlBackend::finalize_version_info() noexcept
{
- if (m_versions != nullptr)
- {
- g_hash_table_destroy (m_versions);
- m_versions = nullptr;
- }
+ m_versions.clear();
}
-int
+unsigned int
GncSqlBackend::get_table_version(const std::string& table_name) const noexcept
{
/* If the db is pristine because it's being saved, the table does not exist. */
if (m_is_pristine_db)
return 0;
- return GPOINTER_TO_INT (g_hash_table_lookup (m_versions,
- table_name.c_str()));
+ auto version = std::find_if(m_versions.begin(), m_versions.end(),
+ [table_name](const VersionPair& version) {
+ return version.first == table_name; });
+ if (version != m_versions.end())
+ return version->second;
+ return 0;
}
/**
@@ -640,40 +624,43 @@ GncSqlBackend::get_table_version(const std::string& table_name) const noexcept
* @return TRUE if successful, FALSE if unsuccessful
*/
bool
-GncSqlBackend::set_table_version (const std::string& table_name, int version) noexcept
+GncSqlBackend::set_table_version (const std::string& table_name,
+ unsigned int version) noexcept
{
- gchar* sql;
- gint cur_version;
- gint status;
-
g_return_val_if_fail (version > 0, false);
- cur_version = get_table_version (table_name);
+ unsigned int cur_version{0};
+ std::stringstream sql;
+ auto ver_entry = std::find_if(m_versions.begin(), m_versions.end(),
+ [table_name](const VersionPair& ver) {
+ return ver.first == table_name; });
+ if (ver_entry != m_versions.end())
+ cur_version = ver_entry->second;
if (cur_version != version)
{
if (cur_version == 0)
{
- sql = g_strdup_printf ("INSERT INTO %s VALUES('%s',%d)", VERSION_TABLE_NAME,
- table_name.c_str(), version);
+ sql << "INSERT INTO " << VERSION_TABLE_NAME << " VALUES('" <<
+ table_name << "'," << version <<")";
+ m_versions.push_back(std::make_pair(table_name, version));
}
else
{
- sql = g_strdup_printf ("UPDATE %s SET %s=%d WHERE %s='%s'", VERSION_TABLE_NAME,
- VERSION_COL_NAME, version,
- TABLE_COL_NAME, table_name.c_str());
+ sql << "UPDATE " << VERSION_TABLE_NAME << " SET " <<
+ VERSION_COL_NAME << "=" << version << " WHERE " <<
+ TABLE_COL_NAME << "='" << table_name << "'";
+ ver_entry->second = version;
}
- status = gnc_sql_execute_nonselect_sql (this, sql);
+ auto stmt = create_statement_from_sql(sql.str());
+ auto status = execute_nonselect_statement (stmt);
if (status == -1)
{
- PERR ("SQL error: %s\n", sql);
+ PERR ("SQL error: %s\n", sql.str().c_str());
qof_backend_set_error ((QofBackend*)this, ERR_BACKEND_SERVER_ERR);
+ return false;
}
- g_free (sql);
}
- g_hash_table_insert (m_versions, g_strdup (table_name.c_str()),
- GINT_TO_POINTER (version));
-
return true;
}
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 15f32e8..35c3220 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -58,6 +58,8 @@ using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
using ColVec = std::vector<GncSqlColumnInfo>;
using StrVec = std::vector<std::string>;
using PairVec = std::vector<std::pair<std::string, std::string>>;
+using VersionPair = std::pair<const std::string, unsigned int>;
+using VersionVec = std::vector<VersionPair>;
class GncSqlConnection;
class GncSqlStatement;
using GncSqlStatementPtr = std::unique_ptr<GncSqlStatement>;
@@ -95,8 +97,8 @@ public:
const EntryVec& col_table) const noexcept;
bool add_columns_to_table(const std::string& table_name,
const EntryVec& col_table) const noexcept;
- int get_table_version(const std::string& table_name) const noexcept;
- bool set_table_version (const std::string& table_name, int version) noexcept;
+ unsigned int get_table_version(const std::string& table_name) const noexcept;
+ bool set_table_version (const std::string& table_name, unsigned int version) noexcept;
QofBook* book() const noexcept { return m_book; }
bool pristine() const noexcept { return m_is_pristine_db; }
@@ -116,7 +118,7 @@ protected:
bool m_loading; /**< We are performing an initial load */
bool m_in_query; /**< We are processing a query */
bool m_is_pristine_db; /**< Are we saving to a new pristine db? */
- GHashTable* m_versions; /**< Version number for each table */
+ VersionVec m_versions; /**< Version number for each table */
const char* m_timespec_format; /**< Format string for SQL for timespec values */
private:
};
commit 885470b3e7c437e5f3b437d8be084c5f6b5017a9
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jul 23 13:38:40 2016 -0700
Replace std::vector<std::string> with StrVec.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index a8739f4..86755d8 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -132,10 +132,10 @@ public:
std::string create_table_ddl(const GncSqlConnection* conn,
const std::string& table_name,
const ColVec& info_vec);
- std::vector<std::string> get_table_list(dbi_conn conn,
+ StrVec get_table_list(dbi_conn conn,
const std::string& dbname);
void append_col_def(std::string& ddl, const GncSqlColumnInfo& info);
- std::vector<std::string> get_index_list (dbi_conn conn);
+ StrVec get_index_list (dbi_conn conn);
void drop_index(dbi_conn conn, const std::string& index);
};
@@ -326,10 +326,10 @@ exit:
LEAVE ("%s", msg);
}
-template<> std::vector<std::string>
+template<> StrVec
GncDbiProviderImpl<DbType::DBI_SQLITE>::get_index_list (dbi_conn conn)
{
- std::vector<std::string> retval;
+ StrVec retval;
const char* errmsg;
dbi_result result = dbi_conn_query (conn,
"SELECT name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_autoindex%'");
@@ -891,10 +891,10 @@ exit:
LEAVE (" ");
}
-template<> std::vector<std::string>
+template<> StrVec
GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
{
- std::vector<std::string> retval;
+ StrVec retval;
const char* errmsg;
auto dbname = dbi_conn_get_option (conn, "dbname");
auto table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
@@ -1213,10 +1213,10 @@ exit:
LEAVE (" ");
}
-template<> std::vector<std::string>
+template<> StrVec
GncDbiProviderImpl<DbType::DBI_PGSQL>::get_index_list (dbi_conn conn)
{
- std::vector<std::string> retval;
+ StrVec retval;
const char* errmsg;
PINFO ("Retrieving postgres index list\n");
auto result = dbi_conn_query (conn,
@@ -2010,10 +2010,10 @@ GncDbiProviderImpl<DbType::DBI_PGSQL>::append_col_def (std::string& ddl,
}
}
-static std::vector<std::string>
+static StrVec
conn_get_table_list (dbi_conn conn, const std::string& dbname)
{
- std::vector<std::string> retval;
+ StrVec retval;
auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), nullptr);
while (dbi_result_next_row (tables) != 0)
{
@@ -2024,7 +2024,7 @@ conn_get_table_list (dbi_conn conn, const std::string& dbname)
return retval;
}
-template<> std::vector<std::string>
+template<> StrVec
GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
const std::string& dbname)
{
@@ -2036,14 +2036,14 @@ GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
return list;
}
-template<> std::vector<std::string>
+template<> StrVec
GncDbiProviderImpl<DbType::DBI_MYSQL>::get_table_list (dbi_conn conn,
const std::string& dbname)
{
return conn_get_table_list (conn, dbname);
}
-template<> std::vector<std::string>
+template<> StrVec
GncDbiProviderImpl<DbType::DBI_PGSQL>::get_table_list (dbi_conn conn,
const std::string& dbname)
{
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index c3ef108..acc7dad 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -160,7 +160,7 @@ public:
dbi_result table_manage_backup(const std::string& table_name, TableOpType op);
/* FIXME: These three friend functions should really be members, but doing
* that is too invasive just yet. */
- bool table_operation (const std::vector<std::string>& table_name_list,
+ bool table_operation (const StrVec& table_name_list,
TableOpType op) noexcept;
std::string add_columns_ddl(const std::string& table_name,
const ColVec& info_vec) const noexcept;
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index f715ab4..86b1678 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -529,8 +529,8 @@ GncDbiSqlConnection::table_manage_backup (const std::string& table_name,
*/
bool
-GncDbiSqlConnection::table_operation(const std::vector<std::string>& table_names,
- TableOpType op) noexcept
+GncDbiSqlConnection::table_operation(const StrVec& table_names,
+ TableOpType op) noexcept
{
const char* dbname = dbi_conn_get_option (m_conn, "dbname");
std::string lock_table{m_lock_table};
commit d1fd223f9fd947e168a5ac5ab2842bc09ef7b23e
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jul 23 12:52:17 2016 -0700
Make conn_table_operation and add_columns_ddl members of GncDbiSqlConnection.
So they don't need to be friends.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index c45288d..a8739f4 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -1344,98 +1344,6 @@ save_may_clobber_data (QofBackend* qbe)
return retval;
}
-/**
- * Perform a specified SQL operation on every table in a
- * database. Possible operations are:
- * * drop: to DROP all tables from the database
- * * empty: to DELETE all records from each table in the database.
- * * backup: Rename every table from "name" to "name_back"
- * * drop_backup: DROP the backup tables.
- * * rollback: DROP the new table "name" and rename "name_back" to
- * "name", restoring the database to its previous state.
- *
- * The intent of the last two is to be able to move an existing table
- * aside, query its contents with a transformation (in 2.4.x this is
- * already done as the contents are loaded completely when a Qof
- * session is started), save them to a new table according to a new
- * database format, and finally drop the backup table; if there's an
- * error during the process, rollback allows returning the table to
- * its original state.
- *
- * @param sql_conn: The sql connection (via dbi) to which the
- * transactions will be sent
- * @param tables: GList of tables to operate on.
- * @param op: The operation to perform.
- * @return Success (TRUE) or failure.
- */
-
-gboolean
-conn_table_operation (GncSqlConnection* sql_conn,
- std::vector<std::string> table_name_list,
- TableOpType op)
-{
- gboolean result = TRUE;
- GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (sql_conn);
- const gchar* dbname = dbi_conn_get_option (conn->m_conn, "dbname");
-
- g_return_val_if_fail (!table_name_list.empty(), FALSE);
-
- for (auto table : table_name_list)
- {
- dbi_result result;
- auto table_name = table.c_str();
- /* Ignore the lock table */
- if (g_strcmp0 (table_name, lock_table) == 0)
- {
- continue;
- }
- do
- {
- conn->init_error ();
- switch (op)
- {
- case rollback:
- {
- auto full_table_name_list =
- conn->m_provider->get_table_list (conn->m_conn, dbname);
- if (std::find (full_table_name_list.begin(),
- full_table_name_list.end(),
- table_name) != full_table_name_list.end())
- {
- result = dbi_conn_queryf (conn->m_conn, "DROP TABLE %s",
- table_name);
- if (result)
- break;
- }
- }
- /* Fall through */
- case backup:
- case drop_backup:
- result = conn->table_manage_backup (table_name, op);
- break;
- case empty:
- result = dbi_conn_queryf (conn->m_conn, "DELETE FROM TABLE %s",
- table_name);
- break;
- case drop:
- default:
- result = dbi_conn_queryf (conn->m_conn, "DROP TABLE %s",
- table_name);
- break;
- }
- }
- while (conn->m_retry);
- if (result != nullptr)
- {
- if (dbi_result_free (result) < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- result = FALSE;
- }
- }
- }
- return result;
-}
/**
* Safely resave a database by renaming all of its tables, recreating
@@ -1459,10 +1367,10 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
ENTER ("book=%p, primary=%p", book, be->m_book);
auto dbname = dbi_conn_get_option (conn->conn(), "dbname");
auto table_list = conn->m_provider->get_table_list (conn->conn(), dbname);
- if (!conn_table_operation (conn, table_list, backup))
+ if (!conn->table_operation (table_list, backup))
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- conn_table_operation (conn, table_list, rollback);
+ conn->table_operation (table_list, rollback);
LEAVE ("Failed to rename tables");
return;
}
@@ -1474,7 +1382,7 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
if (DBI_ERROR_NONE != dbi_conn_error (conn->m_conn, &errmsg))
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- conn_table_operation (conn, table_list, rollback);
+ conn->table_operation (table_list, rollback);
LEAVE ("Failed to drop indexes %s", errmsg);
return;
}
@@ -1483,11 +1391,11 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
gnc_sql_sync_all (be, book);
if (qof_backend_check_error (qbe))
{
- conn_table_operation (conn, table_list, rollback);
+ conn->table_operation (table_list, rollback);
LEAVE ("Failed to create new database tables");
return;
}
- conn_table_operation (conn, table_list, drop_backup);
+ conn->table_operation (table_list, drop_backup);
LEAVE ("book=%p", book);
}
/* ================================================================= */
@@ -1915,28 +1823,6 @@ GncDbiSqlResult::size() const noexcept
/* --------------------------------------------------------- */
-std::string
-add_columns_ddl(const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec)
-{
- std::string ddl;
- const GncDbiSqlConnection* dbi_conn = dynamic_cast<decltype(dbi_conn)>(conn);
-
- g_return_val_if_fail (conn != nullptr, nullptr);
- ddl += "ALTER TABLE " + table_name;
- for (auto const& info : info_vec)
- {
- if (info != *info_vec.begin())
- {
- ddl += ", ";
- }
- ddl += "ADD COLUMN ";
- dbi_conn->m_provider->append_col_def (ddl, info);
- }
- return ddl;
-}
-
template<> void
GncDbiProviderImpl<DbType::DBI_SQLITE>::append_col_def(std::string& ddl,
const GncSqlColumnInfo& info)
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index c82482e..c3ef108 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -160,13 +160,11 @@ public:
dbi_result table_manage_backup(const std::string& table_name, TableOpType op);
/* FIXME: These three friend functions should really be members, but doing
* that is too invasive just yet. */
- friend gboolean conn_table_operation (GncSqlConnection* sql_conn,
- std::vector<std::string> table_name_list,
- TableOpType op);
+ bool table_operation (const std::vector<std::string>& table_name_list,
+ TableOpType op) noexcept;
+ std::string add_columns_ddl(const std::string& table_name,
+ const ColVec& info_vec) const noexcept;
friend void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
- friend std::string add_columns_ddl(const GncSqlConnection* conn,
- const std::string& table_name,
- const ColVec& info_vec);
private:
QofBackend* m_qbe;
@@ -195,8 +193,6 @@ private:
};
-gboolean conn_table_operation (GncSqlConnection* sql_conn,
- GSList* table_name_list, TableOpType op);
void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
std::string add_columns_ddl(const GncSqlConnection* conn,
const std::string& table_name,
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index 38628fc..f715ab4 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -390,7 +390,7 @@ GncDbiSqlConnection::add_columns_to_table(const std::string& table_name,
const ColVec& info_vec)
const noexcept
{
- auto ddl = add_columns_ddl(this, table_name, info_vec);
+ auto ddl = add_columns_ddl(table_name, info_vec);
if (ddl.empty())
return false;
@@ -503,3 +503,108 @@ GncDbiSqlConnection::table_manage_backup (const std::string& table_name,
}
return result;
}
+/**
+ * Perform a specified SQL operation on every table in a
+ * database. Possible operations are:
+ * * drop: to DROP all tables from the database
+ * * empty: to DELETE all records from each table in the database.
+ * * backup: Rename every table from "name" to "name_back"
+ * * drop_backup: DROP the backup tables.
+ * * rollback: DROP the new table "name" and rename "name_back" to
+ * "name", restoring the database to its previous state.
+ *
+ * The intent of the last two is to be able to move an existing table
+ * aside, query its contents with a transformation (in 2.4.x this is
+ * already done as the contents are loaded completely when a Qof
+ * session is started), save them to a new table according to a new
+ * database format, and finally drop the backup table; if there's an
+ * error during the process, rollback allows returning the table to
+ * its original state.
+ *
+ * @param sql_conn: The sql connection (via dbi) to which the
+ * transactions will be sent
+ * @param tables: GList of tables to operate on.
+ * @param op: The operation to perform.
+ * @return Success (TRUE) or failure.
+ */
+
+bool
+GncDbiSqlConnection::table_operation(const std::vector<std::string>& table_names,
+ TableOpType op) noexcept
+{
+ const char* dbname = dbi_conn_get_option (m_conn, "dbname");
+ std::string lock_table{m_lock_table};
+ g_return_val_if_fail (!table_names.empty(), FALSE);
+ bool retval{true};
+ for (auto table : table_names)
+ {
+ dbi_result result;
+ /* Ignore the lock table */
+ if (table == lock_table)
+ {
+ continue;
+ }
+ do
+ {
+ init_error();
+ switch (op)
+ {
+ case rollback:
+ {
+ auto all_tables = m_provider->get_table_list(m_conn, dbname);
+ if (std::find(all_tables.begin(),
+ all_tables.end(), table) != all_tables.end())
+ {
+ result = dbi_conn_queryf (m_conn, "DROP TABLE %s",
+ table.c_str());
+ if (result)
+ break;
+ }
+ }
+ /* Fall through */
+ case backup:
+ case drop_backup:
+ result = table_manage_backup (table, op);
+ break;
+ case empty:
+ result = dbi_conn_queryf (m_conn, "DELETE FROM TABLE %s",
+ table.c_str());
+ break;
+ case drop:
+ default:
+ result = dbi_conn_queryf (m_conn, "DROP TABLE %s", table.c_str());
+ break;
+ }
+ }
+ while (m_retry);
+
+ if (result != nullptr)
+ {
+ if (dbi_result_free (result) < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ retval = false;
+ }
+ }
+ }
+ return retval;
+}
+
+std::string
+GncDbiSqlConnection::add_columns_ddl(const std::string& table_name,
+ const ColVec& info_vec) const noexcept
+{
+ std::string ddl;
+
+ ddl += "ALTER TABLE " + table_name;
+ for (auto const& info : info_vec)
+ {
+ if (info != *info_vec.begin())
+ {
+ ddl += ", ";
+ }
+ ddl += "ADD COLUMN ";
+ m_provider->append_col_def (ddl, info);
+ }
+ return ddl;
+}
commit 6f67e2dd1a52b5ddacab1178d93c1ae761197561
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Jul 21 16:21:59 2016 -0700
Convert GncSqlBackend and GncDbiBackend into a class hierarchy.
This is a rather complex change, because it also begins to separate the
responsibilities of the backends and GncSqlConnection.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 02c736b..c45288d 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -68,14 +68,6 @@ extern "C"
#include "splint-defs.h"
#endif
-#ifdef G_OS_WIN32
-#include <winsock2.h>
-#define GETPID() GetCurrentProcessId()
-#else
-#include <limits.h>
-#include <unistd.h>
-#define GETPID() getpid()
-#endif
/* For direct access to dbi data structs, sadly needed for datetime */
#include <dbi/dbi-dev.h>
@@ -104,7 +96,6 @@ static dbi_inst dbi_instance = nullptr;
#define HAVE_LIBDBI_TO_LONGLONG 0
#endif
-#define GNC_HOST_NAME_MAX 255
#define TRANSACTION_NAME "trans"
static QofLogModule log_module = G_LOG_DOMAIN;
@@ -118,11 +109,10 @@ static gchar lock_table[] = "gnclock";
#define PGSQL_DEFAULT_PORT 5432
#define SQLITE3_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
-#define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
-#define PGSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d %02d%02d%02d"
+#define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
+#define PGSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d %02d%02d%02d"
-static gboolean gnc_dbi_lock_database (QofBackend *qbe, gboolean ignore_lock);
-static void gnc_dbi_unlock (QofBackend *qbe);
+static gboolean gnc_dbi_lock_database (QofBackend*, dbi_conn, gboolean);
static gboolean save_may_clobber_data (QofBackend* qbe);
static GncDbiTestResult conn_test_dbi_library (dbi_conn conn);
@@ -175,23 +165,21 @@ create_tables(const OBEEntry& entry, GncDbiBackend* be)
std::tie(type, obe) = entry;
g_return_if_fail(obe->is_version (GNC_SQL_BACKEND_VERSION));
- obe->create_tables (&be->sql_be);
+ obe->create_tables (be);
}
-static void
+void
sqlite3_error_fn (dbi_conn conn, void* user_data)
{
const gchar* msg;
GncDbiBackend *be = static_cast<decltype(be)>(user_data);
-/* FIXME: GncSqlConnection doesn't have the error calls so we have to dynamic_cast from the connection stored in GncSqlBackend. Yuck. */
- GncDbiSqlConnection *dbi_conn =
- dynamic_cast<decltype(dbi_conn)>(be->sql_be.conn);
int errnum = dbi_conn_error (conn, &msg);
PERR ("DBI error: %s\n", msg);
- dbi_conn->set_error (ERR_BACKEND_MISC, 0, false);
+ if (be->connected())
+ be->set_error (ERR_BACKEND_MISC, 0, false);
}
-static void
+void
gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
const gchar* book_id, gboolean ignore_lock,
gboolean create, gboolean force)
@@ -232,22 +220,18 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
goto exit;
}
-
- if (be->conn != nullptr)
- {
- dbi_conn_close (be->conn);
- }
-
+ be->connect(nullptr);
+ dbi_conn conn;
#if HAVE_LIBDBI_R
if (dbi_instance)
- be->conn = dbi_conn_new_r ("sqlite3", dbi_instance);
+ conn = dbi_conn_new_r ("sqlite3", dbi_instance);
else
PERR ("Attempt to connect with an uninitialized dbi_instance");
#else
- be->conn = dbi_conn_new ("sqlite3");
+ conn = dbi_conn_new ("sqlite3");
#endif
- if (be->conn == nullptr)
+ if (conn == nullptr)
{
PERR ("Unable to create sqlite3 dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
@@ -256,30 +240,30 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
dirname = g_path_get_dirname (filepath);
basename = g_path_get_basename (filepath);
- dbi_conn_error_handler (be->conn, sqlite3_error_fn, be);
+ dbi_conn_error_handler (conn, sqlite3_error_fn, be);
/* dbi-sqlite3 documentation says that sqlite3 doesn't take a "host" option */
- result = dbi_conn_set_option (be->conn, "host", "localhost");
+ result = dbi_conn_set_option (conn, "host", "localhost");
if (result < 0)
{
PERR ("Error setting 'host' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- result = dbi_conn_set_option (be->conn, "dbname", basename);
+ result = dbi_conn_set_option (conn, "dbname", basename);
if (result < 0)
{
PERR ("Error setting 'dbname' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- result = dbi_conn_set_option (be->conn, "sqlite3_dbdir", dirname);
+ result = dbi_conn_set_option (conn, "sqlite3_dbdir", dirname);
if (result < 0)
{
PERR ("Error setting 'sqlite3_dbdir' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- result = dbi_conn_connect (be->conn);
+ result = dbi_conn_connect (conn);
if (result < 0)
{
@@ -288,7 +272,7 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
goto exit;
}
- dbi_test_result = conn_test_dbi_library (be->conn);
+ dbi_test_result = conn_test_dbi_library (conn);
switch (dbi_test_result)
{
case GNC_DBI_PASS:
@@ -311,27 +295,24 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
if (create && !file_exists) /* File didn't exist before, but it */
{
/* does now, and we don't want to */
- dbi_conn_close (be->conn); /* leave it lying around. */
- be->conn = nullptr;
+ dbi_conn_close (conn); /* leave it lying around. */
+ conn = nullptr;
g_unlink (filepath);
}
msg = "Bad DBI Library";
goto exit;
}
- if (!gnc_dbi_lock_database (qbe, ignore_lock))
+ if (!gnc_dbi_lock_database (qbe, conn, ignore_lock))
{
qof_backend_set_error (qbe, ERR_BACKEND_LOCKED);
msg = "Locked";
goto exit;
}
- if (be->sql_be.conn != nullptr)
- {
- delete (be->sql_be.conn);
- }
- be->sql_be.conn = new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_SQLITE>,
- qbe, be->conn);
- be->sql_be.timespec_format = SQLITE3_TIMESPEC_STR_FORMAT;
+ be->connect(nullptr);
+ be->connect(
+ new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_SQLITE>,
+ qbe, conn, lock_table));
/* We should now have a proper session set up.
* Let's start logging */
@@ -378,8 +359,6 @@ static void
mysql_error_fn (dbi_conn conn, void* user_data)
{
GncDbiBackend* be = (GncDbiBackend*)user_data;
- GncDbiSqlConnection* dbi_conn =
- dynamic_cast<decltype(dbi_conn)>(be->sql_be.conn);
const char* msg;
auto err_num = dbi_conn_error (conn, &msg);
@@ -394,7 +373,7 @@ mysql_error_fn (dbi_conn conn, void* user_data)
if (err_num == 1049) // Database doesn't exist
{
PINFO ("DBI error: %s\n", msg);
- be->exists = FALSE;
+ be->set_exists(false);
return;
}
@@ -402,7 +381,7 @@ mysql_error_fn (dbi_conn conn, void* user_data)
* has been initialized. So let's assert it exits here, otherwise
* simply return.
*/
- if (!dbi_conn)
+ if (!be->connected())
{
PINFO ("DBI error: %s\n", msg);
PINFO ("Note: GbcDbiSqlConnection not yet initialized. Skipping further error processing.");
@@ -413,20 +392,18 @@ mysql_error_fn (dbi_conn conn, void* user_data)
if (err_num == 2006) // Server has gone away
{
PINFO ("DBI error: %s - Reconnecting...\n", msg);
- if (dbi_conn)
- dbi_conn->set_error (ERR_BACKEND_CONN_LOST, 1, true);
- dbi_conn->retry_connection(msg);
+ be->set_error (ERR_BACKEND_CONN_LOST, 1, true);
+ be->retry_connection(msg);
}
else if (err_num == 2003) // Unable to connect
{
- dbi_conn->set_error (ERR_BACKEND_CANT_CONNECT, 1, true);
- dbi_conn->retry_connection (msg);
+ be->set_error (ERR_BACKEND_CANT_CONNECT, 1, true);
+ be->retry_connection (msg);
}
else // Any other error
{
PERR ("DBI error: %s\n", msg);
- if (dbi_conn)
- dbi_conn->set_error (ERR_BACKEND_MISC, 0, FALSE);
+ be->set_error (ERR_BACKEND_MISC, 0, FALSE);
}
}
@@ -496,17 +473,17 @@ set_standard_connection_options (QofBackend* qbe, dbi_conn conn,
return TRUE;
}
-
+/* FIXME: Move to GncDbiSqlConnection. */
static gboolean
-gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
+gnc_dbi_lock_database (QofBackend* qbe, dbi_conn conn, gboolean ignore_lock)
{
GncDbiBackend* qe = (GncDbiBackend*)qbe;
- dbi_conn dcon = qe->conn;
+
dbi_result result;
- const gchar* dbname = dbi_conn_get_option (dcon, "dbname");
+ const gchar* dbname = dbi_conn_get_option (conn, "dbname");
/* Create the table if it doesn't exist */
- result = dbi_conn_get_table_list (dcon, dbname, lock_table);
+ result = dbi_conn_get_table_list (conn, dbname, lock_table);
if (! (result && dbi_result_get_numrows (result)))
{
if (result)
@@ -514,13 +491,13 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
dbi_result_free (result);
result = nullptr;
}
- result = dbi_conn_queryf (dcon,
+ result = dbi_conn_queryf (conn,
"CREATE TABLE %s ( Hostname varchar(%d), PID int )", lock_table,
GNC_HOST_NAME_MAX);
- if (dbi_conn_error (dcon, nullptr))
+ if (dbi_conn_error (conn, nullptr))
{
const gchar* errstr;
- dbi_conn_error (dcon, &errstr);
+ dbi_conn_error (conn, &errstr);
PERR ("Error %s creating lock table", errstr);
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
if (result)
@@ -543,7 +520,7 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
}
/* Protect everything with a single transaction to prevent races */
- if ((result = dbi_conn_query (dcon, "BEGIN")))
+ if ((result = dbi_conn_query (conn, "BEGIN")))
{
/* Check for an existing entry; delete it if ignore_lock is true, otherwise fail */
gchar hostname[ GNC_HOST_NAME_MAX + 1 ];
@@ -552,7 +529,7 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
dbi_result_free (result);
result = nullptr;
}
- result = dbi_conn_queryf (dcon, "SELECT * FROM %s", lock_table);
+ result = dbi_conn_queryf (conn, "SELECT * FROM %s", lock_table);
if (result && dbi_result_get_numrows (result))
{
dbi_result_free (result);
@@ -561,15 +538,15 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
{
qof_backend_set_error (qbe, ERR_BACKEND_LOCKED);
/* FIXME: After enhancing the qof_backend_error mechanism, report in the dialog what is the hostname of the machine holding the lock. */
- dbi_conn_query (dcon, "ROLLBACK");
+ dbi_conn_query (conn, "ROLLBACK");
return FALSE;
}
- result = dbi_conn_queryf (dcon, "DELETE FROM %s", lock_table);
+ result = dbi_conn_queryf (conn, "DELETE FROM %s", lock_table);
if (!result)
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
qof_backend_set_message (qbe, "Failed to delete lock record");
- result = dbi_conn_query (dcon, "ROLLBACK");
+ result = dbi_conn_query (conn, "ROLLBACK");
if (result)
{
dbi_result_free (result);
@@ -586,14 +563,14 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
/* Add an entry and commit the transaction */
memset (hostname, 0, sizeof (hostname));
gethostname (hostname, GNC_HOST_NAME_MAX);
- result = dbi_conn_queryf (dcon,
+ result = dbi_conn_queryf (conn,
"INSERT INTO %s VALUES ('%s', '%d')",
lock_table, hostname, (int)GETPID ());
if (!result)
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
qof_backend_set_message (qbe, "Failed to create lock record");
- result = dbi_conn_query (dcon, "ROLLBACK");
+ result = dbi_conn_query (conn, "ROLLBACK");
if (result)
{
dbi_result_free (result);
@@ -606,7 +583,7 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
dbi_result_free (result);
result = nullptr;
}
- result = dbi_conn_query (dcon, "COMMIT");
+ result = dbi_conn_query (conn, "COMMIT");
if (result)
{
dbi_result_free (result);
@@ -624,96 +601,6 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
}
return FALSE;
}
-static void
-gnc_dbi_unlock (QofBackend* qbe)
-{
- GncDbiBackend* qe = (GncDbiBackend*)qbe;
- dbi_conn dcon = qe->conn;
- dbi_result result;
- const gchar* dbname = nullptr;
-
- g_return_if_fail (dcon != nullptr);
- g_return_if_fail (dbi_conn_error (dcon, nullptr) == 0);
-
- dbname = dbi_conn_get_option (dcon, "dbname");
- /* Check if the lock table exists */
- g_return_if_fail (dbname != nullptr);
- result = dbi_conn_get_table_list (dcon, dbname, lock_table);
- if (! (result && dbi_result_get_numrows (result)))
- {
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- PWARN ("No lock table in database, so not unlocking it.");
- return;
- }
- dbi_result_free (result);
-
- result = dbi_conn_query (dcon, "BEGIN");
- if (result)
- {
- /* Delete the entry if it's our hostname and PID */
- gchar hostname[ GNC_HOST_NAME_MAX + 1 ];
-
- dbi_result_free (result);
- result = nullptr;
- memset (hostname, 0, sizeof (hostname));
- gethostname (hostname, GNC_HOST_NAME_MAX);
- result = dbi_conn_queryf (dcon,
- "SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", lock_table, hostname,
- (int)GETPID ());
- if (result && dbi_result_get_numrows (result))
- {
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- result = dbi_conn_queryf (dcon, "DELETE FROM %s", lock_table);
- if (!result)
- {
- PERR ("Failed to delete the lock entry");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- result = dbi_conn_query (dcon, "ROLLBACK");
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- return;
- }
- else
- {
- dbi_result_free (result);
- result = nullptr;
- }
- result = dbi_conn_query (dcon, "COMMIT");
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- return;
- }
- result = dbi_conn_query (dcon, "ROLLBACK");
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- PWARN ("There was no lock entry in the Lock table");
- return;
- }
- if (result)
- {
- dbi_result_free (result);
- result = nullptr;
- }
- PWARN ("Unable to get a lock on LOCK, so failed to clear the lock entry.");
- qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
-}
#define SQL_OPTION_TO_REMOVE "NO_ZERO_DATE"
@@ -815,36 +702,34 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
// Try to connect to the db. If it doesn't exist and the create
// flag is TRUE, we'll need to connect to the 'mysql' db and execute the
// CREATE DATABASE ddl statement there.
- if (be->conn != nullptr)
- {
- dbi_conn_close (be->conn);
- }
+ be->connect(nullptr);
+ dbi_conn conn;
#if HAVE_LIBDBI_R
if (dbi_instance)
- be->conn = dbi_conn_new_r ("mysql", dbi_instance);
+ conn = dbi_conn_new_r ("mysql", dbi_instance);
else
PERR ("Attempt to connect with an uninitialized dbi_instance");
#else
- be->conn = dbi_conn_new ("mysql");
+ conn = dbi_conn_new ("mysql");
#endif
- if (be->conn == nullptr)
+ if (conn == nullptr)
{
PERR ("Unable to create mysql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
goto exit;
}
- dbi_conn_error_handler (be->conn, mysql_error_fn, be);
- if (!set_standard_connection_options (qbe, be->conn, host, portnum, dbname,
+ dbi_conn_error_handler (conn, mysql_error_fn, be);
+ if (!set_standard_connection_options (qbe, conn, host, portnum, dbname,
username, password))
{
goto exit;
}
- be->exists = TRUE;
- result = dbi_conn_connect (be->conn);
+ be->set_exists(true);
+ result = dbi_conn_connect (conn);
if (result == 0)
{
- adjust_sql_options (be->conn);
- dbi_test_result = conn_test_dbi_library (be->conn);
+ adjust_sql_options (conn);
+ dbi_test_result = conn_test_dbi_library (conn);
switch (dbi_test_result)
{
case GNC_DBI_PASS:
@@ -873,12 +758,12 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
goto exit;
}
- success = gnc_dbi_lock_database (qbe, ignore_lock);
+ success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
}
else
{
- if (be->exists)
+ if (be->exists())
{
PERR ("Unable to connect to database '%s'\n", dbname);
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
@@ -889,22 +774,23 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
if (create)
{
dbi_result dresult;
- result = dbi_conn_set_option (be->conn, "dbname", "mysql");
+ result = dbi_conn_set_option (conn, "dbname", "mysql");
if (result < 0)
{
PERR ("Error setting 'dbname' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- result = dbi_conn_connect (be->conn);
+ result = dbi_conn_connect (conn);
if (result < 0)
{
PERR ("Unable to connect to 'mysql' database\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- adjust_sql_options (be->conn);
- dresult = dbi_conn_queryf (be->conn, "CREATE DATABASE %s CHARACTER SET utf8",
+ adjust_sql_options (conn);
+ dresult = dbi_conn_queryf (conn,
+ "CREATE DATABASE %s CHARACTER SET utf8",
dbname);
if (dresult == nullptr)
{
@@ -912,39 +798,40 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- dbi_conn_close (be->conn);
+ dbi_conn_close (conn);
+ conn = nullptr;
// Try again to connect to the db
#if HAVE_LIBDBI_R
if (dbi_instance)
- be->conn = dbi_conn_new_r ("mysql", dbi_instance);
+ conn = dbi_conn_new_r ("mysql", dbi_instance);
else
PERR ("Attempt to connect with an uninitialized dbi_instance");
#else
- be->conn = dbi_conn_new ("mysql");
+ conn = dbi_conn_new ("mysql");
#endif
- if (be->conn == nullptr)
+ if (conn == nullptr)
{
PERR ("Unable to create mysql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
goto exit;
}
- dbi_conn_error_handler (be->conn, mysql_error_fn, be);
- if (!set_standard_connection_options (qbe, be->conn, host, 0, dbname, username,
- password))
+ dbi_conn_error_handler (conn, mysql_error_fn, be);
+ if (!set_standard_connection_options (qbe, conn, host, 0, dbname,
+ username, password))
{
goto exit;
}
- result = dbi_conn_connect (be->conn);
+ result = dbi_conn_connect (conn);
if (result < 0)
{
PERR ("Unable to create database '%s'\n", dbname);
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- adjust_sql_options (be->conn);
- dbi_test_result = conn_test_dbi_library (be->conn);
+ adjust_sql_options (conn);
+ dbi_test_result = conn_test_dbi_library (conn);
switch (dbi_test_result)
{
case GNC_DBI_PASS:
@@ -964,10 +851,10 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
}
if (dbi_test_result != GNC_DBI_PASS)
{
- dbi_conn_queryf (be->conn, "DROP DATABASE %s", dbname);
+ dbi_conn_queryf (conn, "DROP DATABASE %s", dbname);
goto exit;
}
- success = gnc_dbi_lock_database (qbe, ignore_lock);
+ success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
}
else
{
@@ -979,15 +866,11 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
if (success)
{
dbi_result dresult;
-
- if (be->sql_be.conn != nullptr)
- {
- delete (be->sql_be.conn);
- }
- be->sql_be.conn = new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
- qbe, be->conn);
+ be->connect(nullptr);
+ be->connect(
+ new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
+ qbe, conn, lock_table));
}
- be->sql_be.timespec_format = MYSQL_TIMESPEC_STR_FORMAT;
/* We should now have a proper session set up.
* Let's start logging */
@@ -1066,8 +949,6 @@ static void
pgsql_error_fn (dbi_conn conn, void* user_data)
{
GncDbiBackend* be = (GncDbiBackend*)user_data;
- GncDbiSqlConnection* dbi_conn =
- dynamic_cast<decltype(dbi_conn)>(be->sql_be.conn);
const gchar* msg;
(void)dbi_conn_error (conn, &msg);
@@ -1075,32 +956,32 @@ pgsql_error_fn (dbi_conn conn, void* user_data)
g_str_has_suffix (msg, "does not exist\n"))
{
PINFO ("DBI error: %s\n", msg);
- be->exists = FALSE;
- dbi_conn->set_error (ERR_BACKEND_NO_SUCH_DB, 0, FALSE);
+ be->set_exists(false);
+ be->set_error (ERR_BACKEND_NO_SUCH_DB, 0, FALSE);
}
else if (g_strrstr (msg,
"server closed the connection unexpectedly")) // Connection lost
{
- if (dbi_conn == nullptr)
+ if (!be->connected())
{
PWARN ("DBI Error: Connection lost, connection pointer invalid");
return;
}
PINFO ("DBI error: %s - Reconnecting...\n", msg);
- dbi_conn->set_error (ERR_BACKEND_CONN_LOST, 1, true);
- dbi_conn->retry_connection(msg);
+ be->set_error (ERR_BACKEND_CONN_LOST, 1, true);
+ be->retry_connection(msg);
}
- else if (dbi_conn &&
+ else if (be->connected() &&
(g_str_has_prefix (msg, "connection pointer is NULL") ||
g_str_has_prefix (msg, "could not connect to server"))) // No connection
{
- dbi_conn->set_error(ERR_BACKEND_CANT_CONNECT, 1, true);
- dbi_conn->retry_connection (msg);
+ be->set_error(ERR_BACKEND_CANT_CONNECT, 1, true);
+ be->retry_connection (msg);
}
else
{
PERR ("DBI error: %s\n", msg);
- dbi_conn->set_error (ERR_BACKEND_MISC, 0, false);
+ be->set_error (ERR_BACKEND_MISC, 0, false);
}
}
@@ -1144,37 +1025,34 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
// Try to connect to the db. If it doesn't exist and the create
// flag is TRUE, we'll need to connect to the 'postgres' db and execute the
// CREATE DATABASE ddl statement there.
- if (be->conn != nullptr)
- {
- dbi_conn_close (be->conn);
- }
-
+ be->connect(nullptr);
+ dbi_conn conn;
#if HAVE_LIBDBI_R
if (dbi_instance)
- be->conn = dbi_conn_new_r ("pgsql", dbi_instance);
+ conn = dbi_conn_new_r ("pgsql", dbi_instance);
else
PERR ("Attempt to connect with an uninitialized dbi_instance");
#else
- be->conn = dbi_conn_new ("pgsql");
+ conn = dbi_conn_new ("pgsql");
#endif
- if (be->conn == nullptr)
+ if (conn == nullptr)
{
PERR ("Unable to create pgsql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
goto exit;
}
- dbi_conn_error_handler (be->conn, pgsql_error_fn, be);
- if (!set_standard_connection_options (qbe, be->conn, host, portnum, dbnamelc,
+ dbi_conn_error_handler (conn, pgsql_error_fn, be);
+ if (!set_standard_connection_options (qbe, conn, host, portnum, dbnamelc,
username, password))
{
goto exit;
}
- be->exists = TRUE;
- result = dbi_conn_connect (be->conn);
+ be->set_exists(true);
+ result = dbi_conn_connect (conn);
if (result == 0)
{
- dbi_test_result = conn_test_dbi_library (be->conn);
+ dbi_test_result = conn_test_dbi_library (conn);
switch (dbi_test_result)
{
case GNC_DBI_PASS:
@@ -1203,12 +1081,12 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
goto exit;
}
- success = gnc_dbi_lock_database (qbe, ignore_lock);
+ success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
}
else
{
- if (be->exists)
+ if (be->exists())
{
PERR ("Unable to connect to database '%s'\n", dbname);
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
@@ -1219,21 +1097,21 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
if (create)
{
dbi_result dresult;
- result = dbi_conn_set_option (be->conn, "dbname", "postgres");
+ result = dbi_conn_set_option (conn, "dbname", "postgres");
if (result < 0)
{
PERR ("Error setting 'dbname' option\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- result = dbi_conn_connect (be->conn);
+ result = dbi_conn_connect (conn);
if (result < 0)
{
PERR ("Unable to connect to 'postgres' database\n");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- dresult = dbi_conn_queryf (be->conn,
+ dresult = dbi_conn_queryf (conn,
"CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'", dbnamelc);
if (dresult == nullptr)
{
@@ -1241,40 +1119,41 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- dbi_conn_queryf (be->conn,
+ dbi_conn_queryf (conn,
"ALTER DATABASE %s SET standard_conforming_strings TO on", dbnamelc);
- dbi_conn_close (be->conn);
+ dbi_conn_close (conn);
// Try again to connect to the db
#if HAVE_LIBDBI_R
if (dbi_instance)
- be->conn = dbi_conn_new_r ("pgsql", dbi_instance);
+ conn = dbi_conn_new_r ("pgsql", dbi_instance);
else
PERR ("Attempt to connect with an uninitialized dbi_instance");
#else
- be->conn = dbi_conn_new ("pgsql");
+ conn = dbi_conn_new ("pgsql");
#endif
- if (be->conn == nullptr)
+ if (conn == nullptr)
{
PERR ("Unable to create pgsql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
goto exit;
}
- dbi_conn_error_handler (be->conn, pgsql_error_fn, be);
- if (!set_standard_connection_options (qbe, be->conn, host, PGSQL_DEFAULT_PORT,
+ dbi_conn_error_handler (conn, pgsql_error_fn, be);
+ if (!set_standard_connection_options (qbe, conn, host,
+ PGSQL_DEFAULT_PORT,
dbnamelc, username, password))
{
goto exit;
}
- result = dbi_conn_connect (be->conn);
+ result = dbi_conn_connect (conn);
if (result < 0)
{
PERR ("Unable to create database '%s'\n", dbname);
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
goto exit;
}
- dbi_test_result = conn_test_dbi_library (be->conn);
+ dbi_test_result = conn_test_dbi_library (conn);
switch (dbi_test_result)
{
case GNC_DBI_PASS:
@@ -1294,11 +1173,11 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
}
if (GNC_DBI_PASS != dbi_test_result)
{
- dbi_conn_select_db (be->conn, "template1");
- dbi_conn_queryf (be->conn, "DROP DATABASE %s", dbnamelc);
+ dbi_conn_select_db (conn, "template1");
+ dbi_conn_queryf (conn, "DROP DATABASE %s", dbnamelc);
goto exit;
}
- success = gnc_dbi_lock_database (qbe, ignore_lock);
+ success = gnc_dbi_lock_database (qbe, conn, ignore_lock);
}
else
{
@@ -1308,14 +1187,11 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
}
if (success)
{
- if (be->sql_be.conn != nullptr)
- {
- delete (be->sql_be.conn);
- }
- be->sql_be.conn = new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_PGSQL>,
- qbe, be->conn);
+ be->connect(nullptr);
+ be->connect(
+ new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_PGSQL>,
+ qbe, conn, lock_table));
}
- be->sql_be.timespec_format = PGSQL_TIMESPEC_STR_FORMAT;
/* We should now have a proper session set up.
* Let's start logging */
@@ -1370,17 +1246,8 @@ gnc_dbi_session_end (QofBackend* be_start)
ENTER (" ");
- if (be->conn != nullptr)
- {
- gnc_dbi_unlock (be_start);
- be->conn = nullptr;
- }
- if (be->sql_be.conn != nullptr)
- {
- delete (be->sql_be.conn);
- be->sql_be.conn = nullptr;
- }
- gnc_sql_finalize_version_info (&be->sql_be);
+ be->finalize_version_info ();
+ be->connect(nullptr);
LEAVE (" ");
}
@@ -1409,7 +1276,7 @@ gnc_dbi_destroy_backend (QofBackend* be)
* then the database will be loaded read-only. A resave will update
* both values to match this version of Gnucash.
*/
-static void
+void
gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
@@ -1421,10 +1288,10 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
if (loadType == LOAD_TYPE_INITIAL_LOAD)
{
- g_assert (be->sql_be.book == nullptr);
// Set up table version information
- gnc_sql_init_version_info (&be->sql_be);
+ be->init_version_info ();
+ g_assert (be->m_book == nullptr);
// Call all object backends to create any required tables
auto registry = gnc_sql_get_backend_registry();
@@ -1432,9 +1299,9 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
create_tables(entry, be);
}
- gnc_sql_load (&be->sql_be, book, loadType);
+ gnc_sql_load (be, book, loadType);
- if (GNUCASH_RESAVE_VERSION > gnc_sql_get_table_version (&be->sql_be,
+ if (GNUCASH_RESAVE_VERSION > gnc_sql_get_table_version (be,
"Gnucash"))
{
/* The database was loaded with an older database schema or
@@ -1442,7 +1309,7 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
* thing needs to be saved anew. */
qof_backend_set_error (qbe, ERR_SQL_DB_TOO_OLD);
}
- else if (GNUCASH_RESAVE_VERSION < gnc_sql_get_table_version (&be->sql_be,
+ else if (GNUCASH_RESAVE_VERSION < gnc_sql_get_table_version (be,
"Gnucash-Resave"))
{
/* Worse, the database was created with a newer version. We
@@ -1467,8 +1334,8 @@ save_may_clobber_data (QofBackend* qbe)
gboolean retval = FALSE;
/* Data may be clobbered iff the number of tables != 0 */
- dbname = dbi_conn_get_option (be->conn, "dbname");
- result = dbi_conn_get_table_list (be->conn, dbname, nullptr);
+ dbname = dbi_conn_get_option (be->conn(), "dbname");
+ result = dbi_conn_get_table_list (be->conn(), dbname, nullptr);
if (result)
{
retval = dbi_result_get_numrows (result) > 0;
@@ -1583,16 +1450,15 @@ void
gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (((GncSqlBackend*)
- be)->conn);
- const gchar* dbname = nullptr;
+ auto conn = dynamic_cast<GncDbiSqlConnection*>(be->m_conn);
+ g_return_if_fail (conn != nullptr);
g_return_if_fail (be != nullptr);
g_return_if_fail (book != nullptr);
- ENTER ("book=%p, primary=%p", book, be->sql_be.book);
- dbname = dbi_conn_get_option (be->conn, "dbname");
- auto table_list = conn->m_provider->get_table_list (conn->m_conn, dbname);
+ ENTER ("book=%p, primary=%p", book, be->m_book);
+ auto dbname = dbi_conn_get_option (conn->conn(), "dbname");
+ auto table_list = conn->m_provider->get_table_list (conn->conn(), dbname);
if (!conn_table_operation (conn, table_list, backup))
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
@@ -1614,7 +1480,7 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
}
}
- gnc_sql_sync_all (&be->sql_be, book);
+ gnc_sql_sync_all (be, book);
if (qof_backend_check_error (qbe))
{
conn_table_operation (conn, table_list, rollback);
@@ -1633,7 +1499,7 @@ gnc_dbi_begin_edit (QofBackend* qbe, QofInstance* inst)
g_return_if_fail (be != nullptr);
g_return_if_fail (inst != nullptr);
- gnc_sql_begin_edit (&be->sql_be, inst);
+ gnc_sql_begin_edit (be, inst);
}
static void
@@ -1644,7 +1510,7 @@ gnc_dbi_rollback_edit (QofBackend* qbe, QofInstance* inst)
g_return_if_fail (be != nullptr);
g_return_if_fail (inst != nullptr);
- gnc_sql_rollback_edit (&be->sql_be, inst);
+ gnc_sql_rollback_edit (be, inst);
}
static void
@@ -1655,7 +1521,7 @@ gnc_dbi_commit_edit (QofBackend* qbe, QofInstance* inst)
g_return_if_fail (be != nullptr);
g_return_if_fail (inst != nullptr);
- gnc_sql_commit_edit (&be->sql_be, inst);
+ gnc_sql_commit_edit (be, inst);
}
/* ================================================================= */
@@ -1684,22 +1550,17 @@ init_sql_backend (GncDbiBackend* dbi_be)
/* CoA Export function not implemented for the SQL backend. */
be->export_fn = nullptr;
- gnc_sql_init (&dbi_be->sql_be);
-
- dbi_be->sql_be.conn = nullptr;
- dbi_be->sql_be.book = nullptr;
+ gnc_sql_init (dbi_be);
}
static QofBackend*
new_backend (void (*session_begin) (QofBackend*, QofSession*, const gchar*,
- gboolean,
- gboolean,
- gboolean))
+ gboolean, gboolean, gboolean),
+ const char* format)
{
- GncDbiBackend* dbi_be;
QofBackend* be;
- dbi_be = g_new0 (GncDbiBackend, 1);
+ auto dbi_be = new GncDbiBackend(nullptr, nullptr, format);
g_assert (dbi_be != nullptr);
be = (QofBackend*)dbi_be;
@@ -1714,19 +1575,22 @@ new_backend (void (*session_begin) (QofBackend*, QofSession*, const gchar*,
template<> QofBackend*
QofDbiBackendProvider<DbType::DBI_SQLITE>::create_backend()
{
- return new_backend (gnc_dbi_sqlite3_session_begin);
+ return new_backend (gnc_dbi_sqlite3_session_begin,
+ SQLITE3_TIMESPEC_STR_FORMAT);
}
template<> QofBackend*
QofDbiBackendProvider<DbType::DBI_MYSQL>::create_backend()
{
- return new_backend (gnc_dbi_mysql_session_begin);
+ return new_backend (gnc_dbi_mysql_session_begin,
+ MYSQL_TIMESPEC_STR_FORMAT);
}
template<> QofBackend*
QofDbiBackendProvider<DbType::DBI_PGSQL>::create_backend()
{
- return new_backend (gnc_dbi_postgres_session_begin);
+ return new_backend (gnc_dbi_postgres_session_begin,
+ PGSQL_TIMESPEC_STR_FORMAT);
}
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index bbfabb6..c82482e 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -25,8 +25,17 @@
extern "C"
{
#include <dbi/dbi.h>
+#ifdef G_OS_WIN32
+#include <winsock2.h>
+#define GETPID() GetCurrentProcessId()
+#else
+#include <limits.h>
+#include <unistd.h>
+#define GETPID() getpid()
+#endif
}
#include <gnc-backend-sql.h>
+#define GNC_HOST_NAME_MAX 255
/**
* Options to conn_table_operation
@@ -76,22 +85,41 @@ public:
/**
* Implementations of GncSqlBackend.
*/
-struct GncDbiBackend
+class GncDbiBackend : public GncSqlBackend
{
- GncSqlBackend sql_be;
-
- dbi_conn conn;
-
- gboolean exists; // Does the database exist?
+public:
+ GncDbiBackend(GncSqlConnection *conn, QofBook* book,
+ const char* format = nullptr) :
+ GncSqlBackend(conn, book, format), m_exists{false} {}
+ bool connected() const noexcept { return m_conn != nullptr; }
+ /** FIXME: Just a pass-through to m_conn: */
+ void set_error(int error, int repeat, bool retry) noexcept
+ {
+ m_conn->set_error(error, repeat, retry);
+ }
+ void retry_connection(const char* msg) const noexcept
+ {
+ m_conn->retry_connection(msg);
+ }
+ /* Worst of all: */
+ GncSqlConnection* conn() { return m_conn; }
+ /*-----*/
+ bool exists() { return m_exists; }
+ void set_exists(bool exists) { m_exists = exists; }
+ friend void gnc_dbi_load(QofBackend*, QofBook*, QofBackendLoadType);
+ friend void gnc_dbi_safe_sync_all(QofBackend*, QofBook*);
+private:
+ bool m_exists; // Does the database exist?
};
class GncDbiSqlConnection : public GncSqlConnection
{
public:
GncDbiSqlConnection (GncDbiProvider* provider, QofBackend* qbe,
- dbi_conn conn) :
+ dbi_conn conn, const char* lock_table) :
m_qbe{qbe}, m_conn{conn}, m_provider{provider}, m_conn_ok{true},
- m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0}, m_retry{false} {}
+ m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0}, m_retry{false},
+ m_lock_table{lock_table} {}
~GncDbiSqlConnection() override;
GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
noexcept override;
@@ -114,21 +142,21 @@ public:
QofBackend* qbe () const noexcept { return m_qbe; }
dbi_conn conn() const noexcept { return m_conn; }
GncDbiProvider* provider() { return m_provider; }
- inline void set_error (int error, int repeat, bool retry) noexcept
+ inline void set_error(int error, int repeat, bool retry) noexcept override
{
m_last_error = error;
m_error_repeat = repeat;
m_retry = retry;
}
- inline void init_error () noexcept
+ inline void init_error() noexcept
{
set_error(ERR_BACKEND_NO_ERR, 0, false);
}
/** Check if the dbi connection is valid. If not attempt to re-establish it
* Returns TRUE is there is a valid connection in the end or FALSE otherwise
*/
- bool verify() noexcept;
- bool retry_connection(const char* msg) noexcept;
+ bool verify() noexcept override;
+ bool retry_connection(const char* msg) noexcept override;
dbi_result table_manage_backup(const std::string& table_name, TableOpType op);
/* FIXME: These three friend functions should really be members, but doing
* that is too invasive just yet. */
@@ -162,6 +190,8 @@ private:
* original query)
*/
gboolean m_retry;
+ const char* m_lock_table;
+ void unlock_database();
};
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index aaa33fe..38628fc 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -71,10 +71,99 @@ GncDbiSqlStatement::add_where_cond(QofIdTypeConst type_name,
}
}
+void
+GncDbiSqlConnection::unlock_database ()
+{
+ GncDbiBackend* qe = reinterpret_cast<decltype(qe)>(m_qbe);
+
+ if (m_conn == nullptr) return;
+ g_return_if_fail (dbi_conn_error (m_conn, nullptr) == 0);
+
+ auto dbname = dbi_conn_get_option (m_conn, "dbname");
+ /* Check if the lock table exists */
+ g_return_if_fail (dbname != nullptr);
+ auto result = dbi_conn_get_table_list (m_conn, dbname, m_lock_table);
+ if (! (result && dbi_result_get_numrows (result)))
+ {
+ if (result)
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ PWARN ("No lock table in database, so not unlocking it.");
+ return;
+ }
+ dbi_result_free (result);
+
+ result = dbi_conn_query (m_conn, "BEGIN");
+ if (result)
+ {
+ /* Delete the entry if it's our hostname and PID */
+ gchar hostname[ GNC_HOST_NAME_MAX + 1 ];
+
+ dbi_result_free (result);
+ result = nullptr;
+ memset (hostname, 0, sizeof (hostname));
+ gethostname (hostname, GNC_HOST_NAME_MAX);
+ result = dbi_conn_queryf (m_conn,
+ "SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", m_lock_table, hostname,
+ (int)GETPID ());
+ if (result && dbi_result_get_numrows (result))
+ {
+ if (result)
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ result = dbi_conn_queryf (m_conn, "DELETE FROM %s", m_lock_table);
+ if (!result)
+ {
+ PERR ("Failed to delete the lock entry");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ result = dbi_conn_query (m_conn, "ROLLBACK");
+ if (result)
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ return;
+ }
+ else
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ result = dbi_conn_query (m_conn, "COMMIT");
+ if (result)
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ return;
+ }
+ result = dbi_conn_query (m_conn, "ROLLBACK");
+ if (result)
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ PWARN ("There was no lock entry in the Lock table");
+ return;
+ }
+ if (result)
+ {
+ dbi_result_free (result);
+ result = nullptr;
+ }
+ PWARN ("Unable to get a lock on LOCK, so failed to clear the lock entry.");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+}
+
GncDbiSqlConnection::~GncDbiSqlConnection()
{
if (m_conn)
{
+ unlock_database();
dbi_conn_close(m_conn);
m_conn = nullptr;
}
@@ -336,7 +425,8 @@ GncDbiSqlConnection::quote_string (const std::string& unquoted_str)
}
}
-/* Check if the dbi connection is valid. If not attempt to re-establish it
+
+/** Check if the dbi connection is valid. If not attempt to re-establish it
* Returns TRUE is there is a valid connection in the end or FALSE otherwise
*/
bool
diff --git a/src/backend/dbi/gnc-dbisqlconnection.hpp b/src/backend/dbi/gnc-dbisqlconnection.hpp
new file mode 100644
index 0000000..64aedb0
--- /dev/null
+++ b/src/backend/dbi/gnc-dbisqlconnection.hpp
@@ -0,0 +1,29 @@
+/********************************************************************
+ * gnc-dbisqlconnection.hpp: Encapsulate libdbi dbi_conn *
+ * *
+ * Copyright 2016 John Ralls <jralls at ceridwen.us> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+#ifndef _GNC_DBISQLCONNECTION_HPP_
+#define _GNC_DBISQLCONNECTION_HPP_
+/**
+ * Encapsulate a libdbi dbi_conn connection.
+ */
+
+#endif //_GNC_DBISQLCONNECTION_HPP_
diff --git a/src/backend/dbi/test/test-backend-dbi-basic.cpp b/src/backend/dbi/test/test-backend-dbi-basic.cpp
index 73f60d6..7d57e4b 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.cpp
+++ b/src/backend/dbi/test/test-backend-dbi-basic.cpp
@@ -351,12 +351,11 @@ teardown (Fixture* fixture, gconstpointer pData)
test_clear_error_list ();
}
-
+#if 0 //temporarily disable test pending refactor.
static void
test_conn_index_functions (QofBackend* qbe)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (be->sql_be.conn);
auto index_list = conn->provider()->get_index_list (be->conn);
g_test_message ("Returned from index list\n");
@@ -369,7 +368,7 @@ test_conn_index_functions (QofBackend* qbe)
}
}
-
+#endif
/* Given a synthetic session, use the same logic as
* QofSession::save_as to save it to a specified sql url, then load it
* back and compare. */
@@ -485,7 +484,7 @@ test_dbi_safe_save (Fixture* fixture, gconstpointer pData)
compare_books (qof_session_get_book (session_1),
qof_session_get_book (session_2));
be = qof_book_get_backend (qof_session_get_book (session_2));
- test_conn_index_functions (be);
+// test_conn_index_functions (be);
cleanup:
fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
@@ -512,10 +511,9 @@ test_dbi_version_control (Fixture* fixture, gconstpointer pData)
auto url = (gchar*)pData;
QofSession* sess;
QofBook* book;
- QofBackend* qbe;
QofBackendError err;
gint ourversion = gnc_prefs_get_long_version ();
-
+ GncSqlBackend* be;
// Load the session data
if (fixture->filename)
url = fixture->filename;
@@ -531,11 +529,10 @@ test_dbi_version_control (Fixture* fixture, gconstpointer pData)
}
qof_session_swap_data (fixture->session, sess);
qof_session_save (sess, NULL);
- qbe = qof_session_get_backend (sess);
+ be = reinterpret_cast<GncSqlBackend*>(qof_session_get_backend (sess));
book = qof_session_get_book (sess);
qof_book_begin_edit (book);
- gnc_sql_set_table_version ((GncSqlBackend*)qbe,
- "Gnucash", GNUCASH_RESAVE_VERSION - 1);
+ be->set_table_version ("Gnucash", GNUCASH_RESAVE_VERSION - 1);
qof_book_commit_edit (book);
qof_session_end (sess);
qof_session_destroy (sess);
@@ -544,13 +541,11 @@ test_dbi_version_control (Fixture* fixture, gconstpointer pData)
qof_session_load (sess, NULL);
err = qof_session_pop_error (sess);
g_assert_cmpint (err, == , ERR_SQL_DB_TOO_OLD);
- qbe = qof_session_get_backend (sess);
+ be = reinterpret_cast<GncSqlBackend*>(qof_session_get_backend (sess));
book = qof_session_get_book (sess);
qof_book_begin_edit (book);
- gnc_sql_set_table_version ((GncSqlBackend*)qbe,
- "Gnucash", ourversion);
- gnc_sql_set_table_version ((GncSqlBackend*)qbe,
- "Gnucash-Resave", ourversion + 1);
+ be->set_table_version ("Gnucash", ourversion);
+ be->set_table_version ("Gnucash-Resave", ourversion + 1);
qof_book_commit_edit (book);
qof_session_end (sess);
qof_session_destroy (sess);
@@ -561,11 +556,10 @@ test_dbi_version_control (Fixture* fixture, gconstpointer pData)
err = qof_session_pop_error (sess);
g_assert_cmpint (err, == , ERR_SQL_DB_TOO_NEW);
cleanup:
- qbe = qof_session_get_backend (sess);
+ be = reinterpret_cast<GncSqlBackend*>(qof_session_get_backend (sess));
book = qof_session_get_book (sess);
qof_book_begin_edit (book);
- gnc_sql_set_table_version ((GncSqlBackend*)qbe,
- "Gnucash-Resave", GNUCASH_RESAVE_VERSION);
+ be->set_table_version ("Gnucash-Resave", GNUCASH_RESAVE_VERSION);
qof_book_commit_edit (book);
qof_session_end (sess);
qof_session_destroy (sess);
diff --git a/src/backend/dbi/test/test-dbi-stuff.cpp b/src/backend/dbi/test/test-dbi-stuff.cpp
index 3895039..8c80065 100644
--- a/src/backend/dbi/test/test-dbi-stuff.cpp
+++ b/src/backend/dbi/test/test-dbi-stuff.cpp
@@ -210,12 +210,11 @@ compare_lots (QofBook* book_1, QofBook* book_2)
{
do_compare (book_1, book_2, GNC_ID_LOT, compare_single_lot, "Lot lists match");
}
-
+#if 0 //Disable test temporarily
static void
test_conn_index_functions (QofBackend* qbe)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (be->sql_be.conn);
auto index_list = conn->provider()->get_index_list (be->conn);
g_test_message ("Returned from index list\n");
@@ -227,7 +226,7 @@ test_conn_index_functions (QofBackend* qbe)
g_assert (DBI_ERROR_NONE == dbi_conn_error (conn->conn(), &errmsg));
}
}
-
+#endif
static void
compare_pricedbs (QofBook* book_1, QofBook* book_2)
{
diff --git a/src/backend/sql/gnc-account-sql.cpp b/src/backend/sql/gnc-account-sql.cpp
index f0114ff..0831095 100644
--- a/src/backend/sql/gnc-account-sql.cpp
+++ b/src/backend/sql/gnc-account-sql.cpp
@@ -183,11 +183,11 @@ load_single_account (GncSqlBackend* be, GncSqlRow& row,
guid = gnc_sql_load_guid (be, row);
if (guid != NULL)
{
- pAccount = xaccAccountLookup (guid, be->book);
+ pAccount = xaccAccountLookup (guid, be->book());
}
if (pAccount == NULL)
{
- pAccount = xaccMallocAccount (be->book);
+ pAccount = xaccMallocAccount (be->book());
}
xaccAccountBeginEdit (pAccount);
gnc_sql_load_object (be, row, GNC_ID_ACCOUNT, pAccount, col_table);
@@ -196,7 +196,7 @@ load_single_account (GncSqlBackend* be, GncSqlRow& row,
/* If we don't have a parent and this isn't the root account, it might be because the parent
account hasn't been loaded yet. Remember the account and its parent guid for later. */
if (gnc_account_get_parent (pAccount) == NULL
- && pAccount != gnc_book_get_root_account (be->book))
+ && pAccount != gnc_book_get_root_account (be->book()))
{
account_parent_guid_struct* s = static_cast<decltype (s)> (
g_malloc (sizeof (account_parent_guid_struct)));
@@ -222,7 +222,7 @@ GncSqlAccountBackend::load_all (GncSqlBackend* be)
ENTER ("");
- pBook = be->book;
+ pBook = be->book();
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
if (stmt == nullptr)
@@ -256,7 +256,7 @@ GncSqlAccountBackend::load_all (GncSqlBackend* be)
for (elem = l_accounts_needing_parents; elem != NULL;)
{
account_parent_guid_struct* s = (account_parent_guid_struct*)elem->data;
- pParent = xaccAccountLookup (&s->guid, be->book);
+ pParent = xaccAccountLookup (&s->guid, be->book());
if (pParent != NULL)
{
GList* next_elem;
@@ -347,7 +347,7 @@ GncSqlAccountBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -397,7 +397,7 @@ GncSqlColumnTableEntryImpl<CT_ACCOUNTREF>::load (const GncSqlBackend* be,
{
load_from_guid_ref(row, obj_name, pObject,
[be](GncGUID* g){
- return xaccAccountLookup(g, be->book);
+ return xaccAccountLookup(g, be->book());
});
}
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index f51a3a8..b1ced87 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -82,10 +82,12 @@ extern "C"
#include "gnc-tax-table-sql.h"
#include "gnc-vendor-sql.h"
+#define VERSION_TABLE_NAME "versions"
+#define MAX_TABLE_NAME_LEN 50
+#define TABLE_COL_NAME "table_name"
+#define VERSION_COL_NAME "table_version"
+
static void gnc_sql_init_object_handlers (void);
-static void update_progress (GncSqlBackend* be);
-static void finish_progress (GncSqlBackend* be);
-static gboolean reset_version_info (GncSqlBackend* be);
static GncSqlStatementPtr build_insert_statement (GncSqlBackend* be,
const gchar* table_name,
QofIdTypeConst obj_name,
@@ -183,7 +185,7 @@ create_tables(const OBEEntry& entry, GncSqlBackend* be)
GncSqlObjectBackendPtr obe = nullptr;
std::tie(type, obe) = entry;
g_return_if_fail (obe->is_version (GNC_SQL_BACKEND_VERSION));
- update_progress(be);
+ be->update_progress();
obe->create_tables(be);
}
@@ -240,12 +242,12 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
ENTER ("be=%p, book=%p", be, book);
- be->loading = TRUE;
+ be->m_loading = TRUE;
if (loadType == LOAD_TYPE_INITIAL_LOAD)
{
- g_assert (be->book == NULL);
- be->book = book;
+ g_assert (be->m_book == NULL);
+ be->m_book = book;
/* Load any initial stuff. Some of this needs to happen in a certain order */
for (auto type : fixed_load_order)
@@ -253,7 +255,7 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
auto obe = gnc_sql_get_object_backend(type);
if (obe)
{
- update_progress(be);
+ be->update_progress();
obe->load_all (be);
}
}
@@ -262,7 +264,7 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
auto obe = gnc_sql_get_object_backend(type);
if (obe)
{
- update_progress(be);
+ be->update_progress();
obe->load_all (be);
}
}
@@ -284,7 +286,7 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
obe->load_all (be);
}
- be->loading = FALSE;
+ be->m_loading = FALSE;
g_list_free_full (post_load_commodities, commit_commodity);
post_load_commodities = NULL;
@@ -292,7 +294,7 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
* dirty with this backend
*/
qof_book_mark_session_saved (book);
- finish_progress (be);
+ be->finish_progress();
LEAVE ("");
}
@@ -321,7 +323,7 @@ write_account_tree (GncSqlBackend* be, Account* root)
}
g_list_free (descendants);
}
- update_progress (be);
+ be->update_progress();
return is_ok;
}
@@ -333,12 +335,12 @@ write_accounts (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
- update_progress (be);
- is_ok = write_account_tree (be, gnc_book_get_root_account (be->book));
+ be->update_progress();
+ is_ok = write_account_tree (be, gnc_book_get_root_account (be->book()));
if (is_ok)
{
- update_progress (be);
- is_ok = write_account_tree (be, gnc_book_get_template_root (be->book));
+ be->update_progress();
+ is_ok = write_account_tree (be, gnc_book_get_template_root (be->book()));
}
return is_ok;
@@ -360,7 +362,7 @@ write_tx (Transaction* tx, gpointer data)
{
s->is_ok = splitbe->commit(s->be, QOF_INSTANCE(split_node->data));
}
- update_progress (s->be);
+ s->be->update_progress ();
return (s->is_ok ? 0 : 1);
}
@@ -373,8 +375,8 @@ write_transactions (GncSqlBackend* be)
write_objects_t data{be, true, obe};
(void)xaccAccountTreeForEachTransaction (
- gnc_book_get_root_account (be->book), write_tx, &data);
- update_progress (be);
+ gnc_book_get_root_account (be->book()), write_tx, &data);
+ be->update_progress();
return data.is_ok;
}
@@ -385,11 +387,11 @@ write_template_transactions (GncSqlBackend* be)
auto obe = gnc_sql_get_object_backend(GNC_ID_TRANS);
write_objects_t data{be, true, obe};
- auto ra = gnc_book_get_template_root (be->book);
+ auto ra = gnc_book_get_template_root (be->book());
if (gnc_account_n_descendants (ra) > 0)
{
(void)xaccAccountTreeForEachTransaction (ra, write_tx, &data);
- update_progress (be);
+ be->update_progress();
}
return data.is_ok;
@@ -404,7 +406,7 @@ write_schedXactions (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
- schedXactions = gnc_book_get_schedxactions (be->book)->sx_list;
+ schedXactions = gnc_book_get_schedxactions (be->book())->sx_list;
auto obe = gnc_sql_get_object_backend(GNC_ID_SCHEDXACTION);
for (; schedXactions != NULL && is_ok; schedXactions = schedXactions->next)
@@ -412,25 +414,270 @@ write_schedXactions (GncSqlBackend* be)
tmpSX = static_cast<decltype (tmpSX)> (schedXactions->data);
is_ok = obe->commit (be, QOF_INSTANCE (tmpSX));
}
- update_progress (be);
+ be->update_progress();
return is_ok;
}
-static void
-update_progress (GncSqlBackend* be)
+static EntryVec version_table
+{
+ gnc_sql_make_table_entry<CT_STRING>(
+ TABLE_COL_NAME, MAX_TABLE_NAME_LEN, COL_PKEY | COL_NNUL),
+ gnc_sql_make_table_entry<CT_INT>(VERSION_COL_NAME, 0, COL_NNUL)
+};
+
+GncSqlBackend::GncSqlBackend(GncSqlConnection *conn, QofBook* book,
+ const char* format) :
+ be {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, ERR_BACKEND_NO_ERR, nullptr, 0,
+ nullptr}, m_conn{conn}, m_book{book}, m_loading{false},
+ m_in_query{false}, m_is_pristine_db{false}, m_versions{nullptr},
+ m_timespec_format{format}
{
- if (be->be.percentage != NULL)
- (be->be.percentage) (NULL, 101.0);
+ if (conn != nullptr)
+ connect (conn);
}
-static void
-finish_progress (GncSqlBackend* be)
+void
+GncSqlBackend::connect(GncSqlConnection *conn) noexcept
+{
+ if (m_conn != nullptr && m_conn != conn)
+ delete m_conn;
+ if (m_versions != nullptr)
+ finalize_version_info();
+ m_conn = conn;
+}
+
+GncSqlStatementPtr
+GncSqlBackend::create_statement_from_sql(const std::string& str) const noexcept
+{
+ auto stmt = m_conn->create_statement_from_sql(str);
+ if (stmt == nullptr)
+ {
+ PERR ("SQL error: %s\n", str.c_str());
+ qof_backend_set_error ((QofBackend*)this, ERR_BACKEND_SERVER_ERR);
+ }
+ return stmt;
+}
+
+GncSqlResultPtr
+GncSqlBackend::execute_select_statement(const GncSqlStatementPtr& stmt) const noexcept
+{
+ auto result = m_conn->execute_select_statement(stmt);
+ if (result == nullptr)
+ {
+ PERR ("SQL error: %s\n", stmt->to_sql());
+ qof_backend_set_error ((QofBackend*)this, ERR_BACKEND_SERVER_ERR);
+ }
+ return result;
+}
+
+int
+GncSqlBackend::execute_nonselect_statement(const GncSqlStatementPtr& stmt) const noexcept
+{
+ auto result = m_conn->execute_nonselect_statement(stmt);
+ if (result == -1)
+ {
+ PERR ("SQL error: %s\n", stmt->to_sql());
+ qof_backend_set_error ((QofBackend*)this, ERR_BACKEND_SERVER_ERR);
+ }
+ return result;
+}
+
+std::string
+GncSqlBackend::quote_string(const std::string& str) const noexcept
+{
+ return m_conn->quote_string(str);
+}
+
+bool
+GncSqlBackend::create_table(const std::string& table_name,
+ const EntryVec& col_table) const noexcept
+{
+ ColVec info_vec;
+ gboolean ok = FALSE;
+
+ for (auto const& table_row : col_table)
+ {
+ table_row->add_to_table (this, info_vec);
+ }
+ return m_conn->create_table (table_name, info_vec);
+
+}
+
+bool
+GncSqlBackend::create_index(const std::string& index_name,
+ const std::string& table_name,
+ const EntryVec& col_table) const noexcept
+{
+ return m_conn->create_index(index_name, table_name, col_table);
+}
+
+bool
+GncSqlBackend::add_columns_to_table(const std::string& table_name,
+ const EntryVec& col_table) const noexcept
+{
+ ColVec info_vec;
+
+ for (auto const& table_row : col_table)
+ {
+ table_row->add_to_table (this, info_vec);
+ }
+ return m_conn->add_columns_to_table(table_name, info_vec);
+}
+
+void
+GncSqlBackend::update_progress() const noexcept
+{
+ if (be.percentage != nullptr)
+ (be.percentage) (nullptr, 101.0);
+}
+
+void
+GncSqlBackend::finish_progress() const noexcept
+{
+ if (be.percentage != nullptr)
+ (be.percentage) (nullptr, -1.0);
+}
+
+/**
+ * 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.
+ *
+ * @param be Backend struct
+ */
+void
+GncSqlBackend::init_version_info() noexcept
+{
+ if (m_versions != NULL)
+ {
+ g_hash_table_destroy (m_versions);
+ }
+ m_versions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ if (m_conn->does_table_exist (VERSION_TABLE_NAME))
+ {
+ std::string sql {"SELECT * FROM "};
+ sql += VERSION_TABLE_NAME;
+ auto stmt = m_conn->create_statement_from_sql(sql);
+ auto result = m_conn->execute_select_statement (stmt);
+ for (const auto& row : *result)
+ {
+ auto name = row.get_string_at_col (TABLE_COL_NAME);
+ auto version = row.get_int_at_col (VERSION_COL_NAME);
+ g_hash_table_insert (m_versions, g_strdup (name.c_str()),
+ GINT_TO_POINTER (version));
+ }
+ }
+ else
+ {
+ create_table (VERSION_TABLE_NAME, version_table);
+ set_table_version("Gnucash", gnc_prefs_get_long_version ());
+ set_table_version("Gnucash-Resave", GNUCASH_RESAVE_VERSION);
+ }
+}
+
+/**
+ * Resets the version table information by removing all version table info.
+ * It also recreates the version table in the db.
+ *
+ * @param be Backend struct
+ * @return TRUE if successful, FALSE if error
+ */
+bool
+GncSqlBackend::reset_version_info() noexcept
+{
+ bool ok = true;
+ if (!m_conn->does_table_exist (VERSION_TABLE_NAME))
+ ok = create_table (VERSION_TABLE_NAME, version_table);
+ if (m_versions == nullptr)
+ {
+ m_versions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ }
+ else
+ {
+ g_hash_table_remove_all (m_versions);
+ }
+
+ set_table_version ("Gnucash", gnc_prefs_get_long_version ());
+ set_table_version ("Gnucash-Resave", GNUCASH_RESAVE_VERSION);
+ return ok;
+}
+
+/**
+ * Finalizes the version table info by destroying the hash table.
+ *
+ * @param be Backend struct
+ */
+void
+GncSqlBackend::finalize_version_info() noexcept
{
- if (be->be.percentage != NULL)
- (be->be.percentage) (NULL, -1.0);
+ if (m_versions != nullptr)
+ {
+ g_hash_table_destroy (m_versions);
+ m_versions = nullptr;
+ }
}
+int
+GncSqlBackend::get_table_version(const std::string& table_name) const noexcept
+{
+ /* If the db is pristine because it's being saved, the table does not exist. */
+ if (m_is_pristine_db)
+ return 0;
+
+ return GPOINTER_TO_INT (g_hash_table_lookup (m_versions,
+ table_name.c_str()));
+}
+
+/**
+ * Registers the version for a table. Registering involves updating the
+ * db version table and also the hash table.
+ *
+ * @param be Backend struct
+ * @param table_name Table name
+ * @param version Version number
+ * @return TRUE if successful, FALSE if unsuccessful
+ */
+bool
+GncSqlBackend::set_table_version (const std::string& table_name, int version) noexcept
+{
+ gchar* sql;
+ gint cur_version;
+ gint status;
+
+ g_return_val_if_fail (version > 0, false);
+
+ cur_version = get_table_version (table_name);
+ if (cur_version != version)
+ {
+ if (cur_version == 0)
+ {
+ sql = g_strdup_printf ("INSERT INTO %s VALUES('%s',%d)", VERSION_TABLE_NAME,
+ table_name.c_str(), version);
+ }
+ else
+ {
+ sql = g_strdup_printf ("UPDATE %s SET %s=%d WHERE %s='%s'", VERSION_TABLE_NAME,
+ VERSION_COL_NAME, version,
+ TABLE_COL_NAME, table_name.c_str());
+ }
+ status = gnc_sql_execute_nonselect_sql (this, sql);
+ if (status == -1)
+ {
+ PERR ("SQL error: %s\n", sql);
+ qof_backend_set_error ((QofBackend*)this, ERR_BACKEND_SERVER_ERR);
+ }
+ g_free (sql);
+ }
+
+ g_hash_table_insert (m_versions, g_strdup (table_name.c_str()),
+ GINT_TO_POINTER (version));
+
+ return true;
+}
+
+
void
gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
{
@@ -439,18 +686,18 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
g_return_if_fail (be != NULL);
g_return_if_fail (book != NULL);
- ENTER ("book=%p, be->book=%p", book, be->book);
- update_progress (be);
- (void)reset_version_info (be);
+ be->reset_version_info();
+ ENTER ("book=%p, be->book=%p", book, be->book());
+ be->update_progress();
/* Create new tables */
- be->is_pristine_db = TRUE;
+ be->m_is_pristine_db = true;
for(auto entry : backend_registry)
create_tables(entry, be);
/* Save all contents */
- be->book = book;
- is_ok = be->conn->begin_transaction ();
+ be->m_book = book;
+ is_ok = be->m_conn->begin_transaction ();
// FIXME: should write the set of commodities that are used
//write_commodities( be, book );
@@ -482,11 +729,11 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
}
if (is_ok)
{
- is_ok = be->conn->commit_transaction ();
+ is_ok = be->m_conn->commit_transaction ();
}
if (is_ok)
{
- be->is_pristine_db = FALSE;
+ be->m_is_pristine_db = false;
/* Mark the session as clean -- though it shouldn't ever get
* marked dirty with this backend
@@ -497,9 +744,9 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
{
if (!qof_backend_check_error ((QofBackend*)be))
qof_backend_set_error ((QofBackend*)be, ERR_BACKEND_SERVER_ERR);
- is_ok = be->conn->rollback_transaction ();
+ is_ok = be->m_conn->rollback_transaction ();
}
- finish_progress (be);
+ be->finish_progress();
LEAVE ("book=%p", book);
}
@@ -558,15 +805,15 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
g_return_if_fail (be != NULL);
g_return_if_fail (inst != NULL);
- if (qof_book_is_readonly (be->book))
+ if (qof_book_is_readonly (be->book()))
{
qof_backend_set_error ((QofBackend*)be, ERR_BACKEND_READONLY);
- (void)be->conn->rollback_transaction ();
+ (void)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 (be->loading)
+ anything, but do mark the object as clean. */
+ if (be->m_loading)
{
qof_instance_mark_clean (inst);
return;
@@ -576,7 +823,7 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
if (strcmp (inst->e_type, "PriceDB") == 0)
{
qof_instance_mark_clean (inst);
- qof_book_mark_session_saved (be->book);
+ qof_book_mark_session_saved (be->book());
return;
}
@@ -596,7 +843,7 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
return;
}
- if (!be->conn->begin_transaction ())
+ if (!be->m_conn->begin_transaction ())
{
PERR ("gnc_sql_commit_edit(): begin_transaction failed\n");
LEAVE ("Rolled back - database transaction begin error");
@@ -614,10 +861,10 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
if (!be_data.is_known)
{
PERR ("gnc_sql_commit_edit(): Unknown object type '%s'\n", inst->e_type);
- (void)be->conn->rollback_transaction ();
+ (void)be->m_conn->rollback_transaction ();
// Don't let unknown items still mark the book as being dirty
- qof_book_mark_session_saved (be->book);
+ qof_book_mark_session_saved (be->book());
qof_instance_mark_clean (inst);
LEAVE ("Rolled back - unknown object type");
return;
@@ -625,16 +872,16 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
if (!be_data.is_ok)
{
// Error - roll it back
- (void)be->conn->rollback_transaction ();
+ (void)be->m_conn->rollback_transaction ();
// This *should* leave things marked dirty
LEAVE ("Rolled back - database error");
return;
}
- (void)be->conn->commit_transaction ();
+ (void)be->m_conn->commit_transaction ();
- qof_book_mark_session_saved (be->book);
+ qof_book_mark_session_saved (be->book());
qof_instance_mark_clean (inst);
LEAVE ("");
@@ -1011,7 +1258,7 @@ gnc_sql_run_query (QofBackend* pBEnd, gpointer pQuery)
// }
// Mark the book as clean
- qof_instance_mark_clean (QOF_INSTANCE (be->book));
+ qof_instance_mark_clean (QOF_INSTANCE (be->book()));
// DEBUG( "%s\n", (gchar*)pQueryInfo->pCompiledQuery );
@@ -1431,7 +1678,7 @@ gnc_sql_convert_timespec_to_string (const GncSqlBackend* be, Timespec ts)
year = tm->tm_year + 1900;
- datebuf = g_strdup_printf (be->timespec_format,
+ datebuf = g_strdup_printf (be->timespec_format(),
year, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
gnc_tm_free (tm);
return datebuf;
@@ -1794,17 +2041,8 @@ gnc_sql_execute_select_statement (GncSqlBackend* be,
{
g_return_val_if_fail (be != NULL, NULL);
- g_return_val_if_fail (stmt != NULL, NULL);
- auto result = be->conn->execute_select_statement (stmt);
- if (result == NULL)
- {
- PERR ("SQL error: %s\n", stmt->to_sql());
- if (!qof_backend_check_error(&be->be))
- qof_backend_set_error (&be->be, ERR_BACKEND_SERVER_ERR);
- }
-
- return result;
+ return be->execute_select_statement (stmt);
}
GncSqlStatementPtr
@@ -1813,15 +2051,7 @@ gnc_sql_create_statement_from_sql (GncSqlBackend* be, const gchar* sql)
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (sql != NULL, NULL);
- auto stmt = be->conn->create_statement_from_sql (sql);
- if (stmt == nullptr)
- {
- PERR ("SQL error: %s\n", sql);
- if (!qof_backend_check_error(&be->be))
- qof_backend_set_error (&be->be, ERR_BACKEND_SERVER_ERR);
- }
-
- return stmt;
+ return be->create_statement_from_sql (sql);
}
GncSqlResultPtr
@@ -1835,15 +2065,7 @@ gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql)
{
return nullptr;
}
- auto result = be->conn->execute_select_statement (stmt);
- if (result == nullptr)
- {
- PERR ("SQL error: %s\n", sql);
- if (!qof_backend_check_error(&be->be))
- qof_backend_set_error (&be->be, ERR_BACKEND_SERVER_ERR);
- }
-
- return result;
+ return be->execute_select_statement (stmt);
}
gint
@@ -1857,8 +2079,7 @@ gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql)
{
return -1;
}
- auto result = be->conn->execute_nonselect_statement (stmt);
- return result;
+ return be->execute_nonselect_statement (stmt);
}
guint
@@ -1942,7 +2163,7 @@ gnc_sql_do_db_operation (GncSqlBackend* be,
const EntryVec& table)
{
GncSqlStatementPtr stmt;
- gboolean ok = FALSE;
+ bool ok = false;
g_return_val_if_fail (be != NULL, FALSE);
g_return_val_if_fail (table_name != NULL, FALSE);
@@ -1965,20 +2186,8 @@ gnc_sql_do_db_operation (GncSqlBackend* be,
{
g_assert (FALSE);
}
- if (stmt != nullptr)
- {
- auto result = be->conn->execute_nonselect_statement (stmt);
- if (result == -1)
- {
- PERR ("SQL error: %s\n", stmt->to_sql());
- if (!qof_backend_check_error(&be->be))
- qof_backend_set_error (&be->be, ERR_BACKEND_SERVER_ERR);
- }
- else
- {
- ok = TRUE;
- }
- }
+ if (be->execute_nonselect_statement (stmt) != -1)
+ ok = true;
return ok;
}
@@ -2012,11 +2221,11 @@ build_insert_statement (GncSqlBackend* be,
{
if (col_value != *values.begin())
sql << ",";
- sql << be->conn->quote_string(col_value.second);
+ sql << be->quote_string(col_value.second);
}
sql << ")";
- stmt = be->conn->create_statement_from_sql(sql.str());
+ stmt = be->create_statement_from_sql(sql.str());
return stmt;
}
@@ -2045,10 +2254,10 @@ build_update_statement (GncSqlBackend* be,
if (col_value != *values.begin())
sql << ",";
sql << col_value.first << "=" <<
- be->conn->quote_string(col_value.second);
+ be->quote_string(col_value.second);
}
- stmt = be->conn->create_statement_from_sql(sql.str());
+ stmt = be->create_statement_from_sql(sql.str());
/* We want our where condition to be just the first column and
* value, i.e. the guid of the object.
*/
@@ -2071,7 +2280,7 @@ build_delete_statement (GncSqlBackend* be,
g_return_val_if_fail (pObject != NULL, NULL);
sql << "DELETE FROM " << table_name;
- auto stmt = be->conn->create_statement_from_sql (sql.str());
+ auto stmt = be->create_statement_from_sql (sql.str());
/* WHERE */
PairVec values;
@@ -2096,7 +2305,7 @@ GncSqlObjectBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -2126,51 +2335,28 @@ GncSqlObjectBackend::commit (GncSqlBackend* be, QofInstance* inst)
/* ================================================================= */
-static gboolean
-do_create_table (const GncSqlBackend* be, const gchar* table_name,
- const EntryVec& col_table)
-{
- ColVec info_vec;
- gboolean ok = FALSE;
-
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
-
- for (auto const& table_row : col_table)
- {
- table_row->add_to_table (be, info_vec);
- }
- ok = be->conn->create_table (table_name, info_vec);
- return ok;
-}
-
gboolean
-gnc_sql_create_table (GncSqlBackend* be, const char* table_name,
- gint table_version, const EntryVec& col_table)
+gnc_sql_create_table (GncSqlBackend* be, const gchar* table_name,
+ int table_version, const EntryVec& col_table)
{
- gboolean ok;
-
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
-
DEBUG ("Creating %s table\n", table_name);
- ok = do_create_table (be, table_name, col_table);
- if (ok)
- {
- ok = gnc_sql_set_table_version (be, table_name, table_version);
- }
- return ok;
+ if (be->create_table (table_name, col_table))
+ return be->set_table_version (table_name, table_version);
+
+ return false;
}
void
GncSqlObjectBackend::create_tables (GncSqlBackend* be)
{
g_return_if_fail (be != nullptr);
- int version = gnc_sql_get_table_version (be, m_table_name.c_str());
- if (version == 0) //No tables, otherwise version will be >= 1.
- gnc_sql_create_table (be, m_table_name.c_str(),
- m_version, m_col_table);
+ int version = be->get_table_version (m_table_name);
+ if (version == 0) //No tables, otherwise version will be >= 1.
+ {
+ be->create_table(m_table_name, m_col_table);
+ be->set_table_version(m_table_name, m_version);
+ }
else if (version != m_version)
PERR("Version mismatch in table %s, expecting %d but backend is %d."
"Table creation aborted.", m_table_name.c_str(), m_version, version);
@@ -2183,7 +2369,7 @@ gnc_sql_create_temp_table (const GncSqlBackend* be, const gchar* table_name,
g_return_val_if_fail (be != NULL, FALSE);
g_return_val_if_fail (table_name != NULL, FALSE);
- return do_create_table (be, table_name, col_table);
+ return be->create_table (table_name, col_table);
}
gboolean
@@ -2197,7 +2383,7 @@ gnc_sql_create_index (const GncSqlBackend* be, const gchar* index_name,
g_return_val_if_fail (index_name != NULL, FALSE);
g_return_val_if_fail (table_name != NULL, FALSE);
- ok = be->conn->create_index (index_name, table_name, col_table);
+ ok = be->create_index (index_name, table_name, col_table);
return ok;
}
@@ -2206,14 +2392,7 @@ gnc_sql_get_table_version (const GncSqlBackend* be, const gchar* table_name)
{
g_return_val_if_fail (be != NULL, 0);
g_return_val_if_fail (table_name != NULL, 0);
-
- /* If the db is pristine because it's being saved, the table does not exist. */
- if (be->is_pristine_db)
- {
- return 0;
- }
-
- return GPOINTER_TO_INT (g_hash_table_lookup (be->versions, table_name));
+ return be->get_table_version(table_name);
}
/* Create a temporary table, copy the data from the old table, delete the
@@ -2252,169 +2431,14 @@ gnc_sql_upgrade_table (GncSqlBackend* be, const gchar* table_name,
gboolean gnc_sql_add_columns_to_table (GncSqlBackend* be, const gchar* table_name,
const EntryVec& new_col_table)
{
- ColVec info_vec;
- gboolean ok = FALSE;
-
g_return_val_if_fail (be != NULL, FALSE);
g_return_val_if_fail (table_name != NULL, FALSE);
- for (auto const& table_row : new_col_table)
- {
- table_row->add_to_table (be, info_vec);
- }
- ok = be->conn->add_columns_to_table(table_name, info_vec);
- return ok;
+ return be->add_columns_to_table(table_name, new_col_table);
}
/* ================================================================= */
-#define VERSION_TABLE_NAME "versions"
-#define MAX_TABLE_NAME_LEN 50
-#define TABLE_COL_NAME "table_name"
-#define VERSION_COL_NAME "table_version"
-
-static EntryVec version_table
-{
- gnc_sql_make_table_entry<CT_STRING>(
- TABLE_COL_NAME, MAX_TABLE_NAME_LEN, COL_PKEY | COL_NNUL),
- gnc_sql_make_table_entry<CT_INT>(VERSION_COL_NAME, 0, COL_NNUL)
-};
-
-/**
- * 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.
- *
- * @param be Backend struct
- */
-void
-gnc_sql_init_version_info (GncSqlBackend* be)
-{
- g_return_if_fail (be != NULL);
-
- if (be->versions != NULL)
- {
- g_hash_table_destroy (be->versions);
- }
- be->versions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
- if (be->conn->does_table_exist (VERSION_TABLE_NAME))
- {
- auto sql = g_strdup_printf ("SELECT * FROM %s", VERSION_TABLE_NAME);
- auto result = gnc_sql_execute_select_sql (be, sql);
- g_free (sql);
- for (const auto& row : *result)
- {
- auto name = row.get_string_at_col (TABLE_COL_NAME);
- auto version = row.get_int_at_col (VERSION_COL_NAME);
- g_hash_table_insert (be->versions, g_strdup (name.c_str()),
- GINT_TO_POINTER (version));
- }
- }
- else
- {
- do_create_table (be, VERSION_TABLE_NAME, version_table);
- gnc_sql_set_table_version (be, "Gnucash",
- gnc_prefs_get_long_version ());
- gnc_sql_set_table_version (be, "Gnucash-Resave",
- GNUCASH_RESAVE_VERSION);
- }
-}
-
-/**
- * Resets the version table information by removing all version table info.
- * It also recreates the version table in the db.
- *
- * @param be Backend struct
- * @return TRUE if successful, FALSE if error
- */
-static gboolean
-reset_version_info (GncSqlBackend* be)
-{
- gboolean ok;
-
- g_return_val_if_fail (be != NULL, FALSE);
-
- ok = do_create_table (be, VERSION_TABLE_NAME, version_table);
- if (be->versions == NULL)
- {
- be->versions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- }
- else
- {
- g_hash_table_remove_all (be->versions);
- }
-
- gnc_sql_set_table_version (be, "Gnucash", gnc_prefs_get_long_version ());
- gnc_sql_set_table_version (be, "Gnucash-Resave", GNUCASH_RESAVE_VERSION);
- return ok;
-}
-
-/**
- * Finalizes the version table info by destroying the hash table.
- *
- * @param be Backend struct
- */
-void
-gnc_sql_finalize_version_info (GncSqlBackend* be)
-{
- g_return_if_fail (be != NULL);
- if (be->versions != NULL)
- {
- g_hash_table_destroy (be->versions);
- be->versions = NULL;
- }
-}
-
-/**
- * Registers the version for a table. Registering involves updating the
- * db version table and also the hash table.
- *
- * @param be Backend struct
- * @param table_name Table name
- * @param version Version number
- * @return TRUE if successful, FALSE if unsuccessful
- */
-gboolean
-gnc_sql_set_table_version (GncSqlBackend* be, const gchar* table_name,
- gint version)
-{
- gchar* sql;
- gint cur_version;
- gint status;
-
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
- g_return_val_if_fail (version > 0, FALSE);
-
- cur_version = gnc_sql_get_table_version (be, table_name);
- if (cur_version != version)
- {
- if (cur_version == 0)
- {
- sql = g_strdup_printf ("INSERT INTO %s VALUES('%s',%d)", VERSION_TABLE_NAME,
- table_name, version);
- }
- else
- {
- sql = g_strdup_printf ("UPDATE %s SET %s=%d WHERE %s='%s'", VERSION_TABLE_NAME,
- VERSION_COL_NAME, version,
- TABLE_COL_NAME, table_name);
- }
- status = gnc_sql_execute_nonselect_sql (be, sql);
- if (status == -1)
- {
- PERR ("SQL error: %s\n", sql);
- if (!qof_backend_check_error(&be->be))
- qof_backend_set_error (&be->be, ERR_BACKEND_SERVER_ERR);
- }
- g_free (sql);
- }
-
- g_hash_table_insert (be->versions, g_strdup (table_name),
- GINT_TO_POINTER (version));
-
- return TRUE;
-}
/* This is necessary for 64-bit builds because g++ complains
* that reinterpret_casting a void* (64 bits) to an int (32 bits)
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 734cbb7..15f32e8 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -59,22 +59,66 @@ using ColVec = std::vector<GncSqlColumnInfo>;
using StrVec = std::vector<std::string>;
using PairVec = std::vector<std::pair<std::string, std::string>>;
class GncSqlConnection;
+class GncSqlStatement;
+using GncSqlStatementPtr = std::unique_ptr<GncSqlStatement>;
+class GncSqlResult;
+//using GncSqlResultPtr = std::unique_ptr<GncSqlResult>;
+using GncSqlResultPtr = GncSqlResult*;
/**
* @struct GncSqlBackend
*
* Main SQL backend structure.
*/
-struct GncSqlBackend
+class GncSqlBackend
{
- QofBackend be; /**< QOF backend */
- GncSqlConnection* conn; /**< SQL connection */
- QofBook* book; /**< The primary, main open book */
- gboolean loading; /**< We are performing an initial load */
- gboolean in_query; /**< We are processing a query */
- gboolean is_pristine_db; /**< Are we saving to a new pristine db? */
- GHashTable* versions; /**< Version number for each table */
- const gchar* timespec_format; /**< Format string for SQL for timespec values */
+public:
+ GncSqlBackend(GncSqlConnection *conn, QofBook* book,
+ const char* format = nullptr);
+ virtual ~GncSqlBackend() = default;
+ /** Connect the backend to a GncSqlConnection.
+ * Sets up version info. Calling with nullptr clears the connection and
+ * destroys the version info.
+ */
+ void connect(GncSqlConnection *conn) noexcept;
+ void init_version_info() noexcept;
+ bool reset_version_info() noexcept;
+ void finalize_version_info() noexcept;
+ /* FIXME: These are just pass-throughs of m_conn functions. */
+ GncSqlStatementPtr create_statement_from_sql(const std::string& str) const noexcept;
+ GncSqlResultPtr execute_select_statement(const GncSqlStatementPtr& stmt) const noexcept;
+ int execute_nonselect_statement(const GncSqlStatementPtr& stmt) const noexcept;
+ std::string quote_string(const std::string&) const noexcept;
+ bool create_table(const std::string& table_name, const EntryVec& col_table) const noexcept;
+ bool create_index(const std::string& index_name,
+ const std::string& table_name,
+ const EntryVec& col_table) const noexcept;
+ bool add_columns_to_table(const std::string& table_name,
+ const EntryVec& col_table) const noexcept;
+ int get_table_version(const std::string& table_name) const noexcept;
+ bool set_table_version (const std::string& table_name, int version) noexcept;
+ QofBook* book() const noexcept { return m_book; }
+
+ bool pristine() const noexcept { return m_is_pristine_db; }
+ void update_progress() const noexcept;
+ void finish_progress() const noexcept;
+ void set_loading(bool val) noexcept { m_loading = val; }
+ const char* timespec_format() const noexcept { return m_timespec_format; }
+
+ friend void gnc_sql_load(GncSqlBackend*, QofBook*, QofBackendLoadType);
+ friend void gnc_sql_sync_all(GncSqlBackend*, QofBook*);
+ friend void gnc_sql_commit_edit(GncSqlBackend*, QofInstance*);
+
+protected:
+ QofBackend be; /**< QOF backend. Not a pointer, nor really a member */
+ GncSqlConnection* m_conn; /**< SQL connection */
+ QofBook* m_book; /**< The primary, main open book */
+ bool m_loading; /**< We are performing an initial load */
+ bool m_in_query; /**< We are processing a query */
+ bool m_is_pristine_db; /**< Are we saving to a new pristine db? */
+ GHashTable* m_versions; /**< Version number for each table */
+ const char* m_timespec_format; /**< Format string for SQL for timespec values */
+private:
};
/**
@@ -137,9 +181,6 @@ void gnc_sql_commit_edit (GncSqlBackend* qbe, QofInstance* inst);
/**
*/
-class GncSqlResult;
-//using GncSqlResultPtr = std::unique_ptr<GncSqlResult>;
-using GncSqlResultPtr = GncSqlResult*;
/**
* SQL statement provider.
@@ -152,8 +193,6 @@ public:
virtual void add_where_cond (QofIdTypeConst, const PairVec&) = 0;
};
-using GncSqlStatementPtr = std::unique_ptr<GncSqlStatement>;
-
/**
* Encapsulate the connection to the database.
*/
@@ -192,6 +231,10 @@ public:
* If not 0 will normally be meaningless outside of implementation code.
*/
virtual int dberror() const noexcept = 0;
+ virtual void set_error(int error, int repeat, bool retry) noexcept = 0;
+ virtual bool verify() noexcept = 0;
+ virtual bool retry_connection(const char* msg) noexcept = 0;
+
};
/**
diff --git a/src/backend/sql/gnc-bill-term-sql.cpp b/src/backend/sql/gnc-bill-term-sql.cpp
index 28cb6b2..e4054d7 100644
--- a/src/backend/sql/gnc-bill-term-sql.cpp
+++ b/src/backend/sql/gnc-bill-term-sql.cpp
@@ -197,10 +197,10 @@ load_single_billterm (GncSqlBackend* be, GncSqlRow& row,
g_return_val_if_fail (be != NULL, NULL);
guid = gnc_sql_load_guid (be, row);
- pBillTerm = gncBillTermLookup (be->book, guid);
+ pBillTerm = gncBillTermLookup (be->book(), guid);
if (pBillTerm == NULL)
{
- pBillTerm = gncBillTermCreate (be->book);
+ pBillTerm = gncBillTermCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_BILLTERM, pBillTerm, col_table);
@@ -298,7 +298,7 @@ GncSqlBillTermBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data {be, true, this};
- qof_object_foreach (GNC_ID_BILLTERM, be->book, do_save_billterm, &data);
+ qof_object_foreach (GNC_ID_BILLTERM, be->book(), do_save_billterm, &data);
return data.is_ok;
}
@@ -319,7 +319,7 @@ GncSqlBillTermBackend::create_tables (GncSqlBackend* be)
{
/* Upgrade 64 bit int handling */
gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
- gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Billterms table upgraded from version 1 to version %d\n",
TABLE_VERSION);
@@ -336,7 +336,7 @@ GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::load (const GncSqlBackend* be,
{
load_from_guid_ref(row, obj_name, pObject,
[be](GncGUID* g){
- return gncBillTermLookup(be->book, g);
+ return gncBillTermLookup(be->book(), g);
});
}
diff --git a/src/backend/sql/gnc-book-sql.cpp b/src/backend/sql/gnc-book-sql.cpp
index 081a744..5e4b4b5 100644
--- a/src/backend/sql/gnc-book-sql.cpp
+++ b/src/backend/sql/gnc-book-sql.cpp
@@ -152,7 +152,7 @@ load_single_book (GncSqlBackend* be, GncSqlRow& row)
gnc_sql_load_guid (be, row);
- pBook = be->book;
+ pBook = be->book();
if (pBook == NULL)
{
pBook = qof_book_new ();
@@ -182,9 +182,9 @@ GncSqlBookBackend::load_all (GncSqlBackend* be)
*/
if (row == result->end())
{
- be->loading = FALSE;
- commit(be, QOF_INSTANCE (be->book));
- be->loading = TRUE;
+ be->set_loading(false);
+ commit (be, QOF_INSTANCE (be->book()));
+ be->set_loading(true);
}
else
{
diff --git a/src/backend/sql/gnc-budget-sql.cpp b/src/backend/sql/gnc-budget-sql.cpp
index 8c76172..96aee9f 100644
--- a/src/backend/sql/gnc-budget-sql.cpp
+++ b/src/backend/sql/gnc-budget-sql.cpp
@@ -275,7 +275,7 @@ save_budget_amounts (GncSqlBackend* be, GncBudget* budget)
info.budget = budget;
num_periods = gnc_budget_get_num_periods (budget);
descendants = gnc_account_get_descendants (gnc_book_get_root_account (
- be->book));
+ be->book()));
for (node = descendants; node != NULL && is_ok; node = g_list_next (node))
{
guint i;
@@ -308,11 +308,11 @@ load_single_budget (GncSqlBackend* be, GncSqlRow& row)
guid = gnc_sql_load_guid (be, row);
if (guid != NULL)
{
- pBudget = gnc_budget_lookup (guid, be->book);
+ pBudget = gnc_budget_lookup (guid, be->book());
}
if (pBudget == NULL)
{
- pBudget = gnc_budget_new (be->book);
+ pBudget = gnc_budget_new (be->book());
}
gnc_budget_begin_edit (pBudget);
@@ -398,7 +398,7 @@ GncSqlBudgetBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -464,7 +464,7 @@ GncSqlBudgetBackend::write (GncSqlBackend* be)
data.be = be;
data.is_ok = TRUE;
data.obe = this;
- qof_collection_foreach (qof_book_get_collection (be->book, GNC_ID_BUDGET),
+ qof_collection_foreach (qof_book_get_collection (be->book(), GNC_ID_BUDGET),
(QofInstanceForeachCB)do_save, &data);
return data.is_ok;
@@ -479,7 +479,7 @@ GncSqlColumnTableEntryImpl<CT_BUDGETREF>::load (const GncSqlBackend* be,
{
load_from_guid_ref(row, obj_name, pObject,
[be](GncGUID* g){
- return gnc_budget_lookup (g, be->book);
+ return gnc_budget_lookup (g, be->book());
});
}
diff --git a/src/backend/sql/gnc-commodity-sql.cpp b/src/backend/sql/gnc-commodity-sql.cpp
index efac9ac..7b1ca5b 100644
--- a/src/backend/sql/gnc-commodity-sql.cpp
+++ b/src/backend/sql/gnc-commodity-sql.cpp
@@ -129,7 +129,7 @@ set_quote_source_name (gpointer pObject, gpointer pValue)
static gnc_commodity*
load_single_commodity (GncSqlBackend* be, GncSqlRow& row)
{
- QofBook* pBook = be->book;
+ QofBook* pBook = be->book();
gnc_commodity* pCommodity;
pCommodity = gnc_commodity_new (pBook, NULL, NULL, NULL, NULL, 100);
@@ -145,7 +145,7 @@ GncSqlCommodityBackend::load_all (GncSqlBackend* be)
{
gnc_commodity_table* pTable;
- pTable = gnc_commodity_table_get_table (be->book);
+ pTable = gnc_commodity_table_get_table (be->book());
auto stmt = gnc_sql_create_select_statement (be, COMMODITIES_TABLE);
if (stmt == nullptr) return;
auto result = gnc_sql_execute_select_statement (be, stmt);
@@ -186,7 +186,7 @@ do_commit_commodity (GncSqlBackend* be, QofInstance* inst,
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant || force_insert)
+ else if (be->pristine() || is_infant || force_insert)
{
op = OP_DB_INSERT;
}
@@ -268,7 +268,7 @@ GncSqlColumnTableEntryImpl<CT_COMMODITYREF>::load (const GncSqlBackend* be,
{
load_from_guid_ref(row, obj_name, pObject,
[be](GncGUID* g){
- return gnc_commodity_find_commodity_by_guid(g, be->book);
+ return gnc_commodity_find_commodity_by_guid(g, be->book());
});
}
diff --git a/src/backend/sql/gnc-customer-sql.cpp b/src/backend/sql/gnc-customer-sql.cpp
index 43bce7f..de77b24 100644
--- a/src/backend/sql/gnc-customer-sql.cpp
+++ b/src/backend/sql/gnc-customer-sql.cpp
@@ -110,10 +110,10 @@ load_single_customer (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
guid = gnc_sql_load_guid (be, row);
- pCustomer = gncCustomerLookup (be->book, guid);
+ pCustomer = gncCustomerLookup (be->book(), guid);
if (pCustomer == NULL)
{
- pCustomer = gncCustomerCreate (be->book);
+ pCustomer = gncCustomerCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_CUSTOMER, pCustomer, col_table);
qof_instance_mark_clean (QOF_INSTANCE (pCustomer));
@@ -164,7 +164,7 @@ GncSqlCustomerBackend::create_tables (GncSqlBackend* be)
{
/* Upgrade 64 bit int handling */
gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
- gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Customers table upgraded from version 1 to version %d\n",
TABLE_VERSION);
@@ -214,7 +214,7 @@ GncSqlCustomerBackend::write (GncSqlBackend* be)
data.be = be;
data.is_ok = TRUE;
data.obe = this;
- qof_object_foreach (GNC_ID_CUSTOMER, be->book, write_single_customer,
+ qof_object_foreach (GNC_ID_CUSTOMER, be->book(), write_single_customer,
(gpointer)&data);
return data.is_ok;
}
diff --git a/src/backend/sql/gnc-employee-sql.cpp b/src/backend/sql/gnc-employee-sql.cpp
index 166596a..f295a5d 100644
--- a/src/backend/sql/gnc-employee-sql.cpp
+++ b/src/backend/sql/gnc-employee-sql.cpp
@@ -96,10 +96,10 @@ load_single_employee (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
guid = gnc_sql_load_guid (be, row);
- pEmployee = gncEmployeeLookup (be->book, guid);
+ pEmployee = gncEmployeeLookup (be->book(), guid);
if (pEmployee == NULL)
{
- pEmployee = gncEmployeeCreate (be->book);
+ pEmployee = gncEmployeeCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_EMPLOYEE, pEmployee, col_table);
qof_instance_mark_clean (QOF_INSTANCE (pEmployee));
@@ -151,7 +151,7 @@ GncSqlEmployeeBackend::create_tables (GncSqlBackend* be)
{
/* Upgrade 64 bit int handling */
gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
- gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Employees table upgraded from version 1 to version %d\n",
TABLE_VERSION);
@@ -179,7 +179,7 @@ GncSqlEmployeeBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -259,7 +259,7 @@ GncSqlEmployeeBackend::write (GncSqlBackend* be)
data.be = be;
data.is_ok = TRUE;
data.obe = this;
- qof_object_foreach (GNC_ID_EMPLOYEE, be->book, write_single_employee, &data);
+ qof_object_foreach (GNC_ID_EMPLOYEE, be->book(), write_single_employee, &data);
return data.is_ok;
}
diff --git a/src/backend/sql/gnc-entry-sql.cpp b/src/backend/sql/gnc-entry-sql.cpp
index c9ca9c1..3f0623d 100644
--- a/src/backend/sql/gnc-entry-sql.cpp
+++ b/src/backend/sql/gnc-entry-sql.cpp
@@ -178,10 +178,10 @@ load_single_entry (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
guid = gnc_sql_load_guid (be, row);
- pEntry = gncEntryLookup (be->book, guid);
+ pEntry = gncEntryLookup (be->book(), guid);
if (pEntry == NULL)
{
- pEntry = gncEntryCreate (be->book);
+ pEntry = gncEntryCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_ENTRY, pEntry, col_table);
qof_instance_mark_clean (QOF_INSTANCE (pEntry));
@@ -234,7 +234,7 @@ GncSqlEntryBackend::create_tables (GncSqlBackend* be)
2->3: "entered" -> "date_entered", and it can be NULL
*/
gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
- gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Entries table upgraded from version %d to version %d\n", version,
TABLE_VERSION);
@@ -267,7 +267,7 @@ GncSqlEntryBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data{be, true, this};
- qof_object_foreach (GNC_ID_ENTRY, be->book, write_single_entry, &data);
+ qof_object_foreach (GNC_ID_ENTRY, be->book(), write_single_entry, &data);
return data.is_ok;
}
diff --git a/src/backend/sql/gnc-invoice-sql.cpp b/src/backend/sql/gnc-invoice-sql.cpp
index e3e5b03..d6d8f5d 100644
--- a/src/backend/sql/gnc-invoice-sql.cpp
+++ b/src/backend/sql/gnc-invoice-sql.cpp
@@ -117,10 +117,10 @@ load_single_invoice (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
guid = gnc_sql_load_guid (be, row);
- pInvoice = gncInvoiceLookup (be->book, guid);
+ pInvoice = gncInvoiceLookup (be->book(), guid);
if (pInvoice == NULL)
{
- pInvoice = gncInvoiceCreate (be->book);
+ pInvoice = gncInvoiceCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_INVOICE, pInvoice, col_table);
qof_instance_mark_clean (QOF_INSTANCE (pInvoice));
@@ -173,7 +173,7 @@ GncSqlInvoiceBackend::create_tables (GncSqlBackend* be)
2->3: invoice open date can be NULL
*/
gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
- gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Invoices table upgraded from version %d to version %d\n", version,
TABLE_VERSION);
@@ -201,7 +201,7 @@ GncSqlInvoiceBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -277,7 +277,7 @@ GncSqlInvoiceBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data{be, true, this};
- qof_object_foreach (GNC_ID_INVOICE, be->book, write_single_invoice, &data);
+ qof_object_foreach (GNC_ID_INVOICE, be->book(), write_single_invoice, &data);
return data.is_ok;
}
@@ -291,7 +291,7 @@ GncSqlColumnTableEntryImpl<CT_INVOICEREF>::load (const GncSqlBackend* be,
{
load_from_guid_ref(row, obj_name, pObject,
[be](GncGUID* g){
- return gncInvoiceLookup (be->book, g);
+ return gncInvoiceLookup (be->book(), g);
});
}
diff --git a/src/backend/sql/gnc-job-sql.cpp b/src/backend/sql/gnc-job-sql.cpp
index da052c4..cb03233 100644
--- a/src/backend/sql/gnc-job-sql.cpp
+++ b/src/backend/sql/gnc-job-sql.cpp
@@ -89,10 +89,10 @@ load_single_job (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
guid = gnc_sql_load_guid (be, row);
- pJob = gncJobLookup (be->book, guid);
+ pJob = gncJobLookup (be->book(), guid);
if (pJob == NULL)
{
- pJob = gncJobCreate (be->book);
+ pJob = gncJobCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_JOB, pJob, col_table);
qof_instance_mark_clean (QOF_INSTANCE (pJob));
@@ -164,7 +164,7 @@ GncSqlJobBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data{be, true, this};
- qof_object_foreach (GNC_ID_JOB, be->book, write_single_job, &data);
+ qof_object_foreach (GNC_ID_JOB, be->book(), write_single_job, &data);
return data.is_ok;
}
diff --git a/src/backend/sql/gnc-lots-sql.cpp b/src/backend/sql/gnc-lots-sql.cpp
index 4e3bebe..ce4fcda 100644
--- a/src/backend/sql/gnc-lots-sql.cpp
+++ b/src/backend/sql/gnc-lots-sql.cpp
@@ -113,7 +113,7 @@ load_single_lot (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
- lot = gnc_lot_new (be->book);
+ lot = gnc_lot_new (be->book());
gnc_lot_begin_edit (lot);
gnc_sql_load_object (be, row, GNC_ID_LOT, lot, col_table);
@@ -166,7 +166,7 @@ GncSqlLotsBackend::create_tables (GncSqlBackend* be)
old table, then rename the new one. */
gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
- (void)gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Lots table upgraded from version 1 to version %d\n", TABLE_VERSION);
}
@@ -189,7 +189,7 @@ GncSqlLotsBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data{be, true, this};
- qof_collection_foreach (qof_book_get_collection (be->book, GNC_ID_LOT),
+ qof_collection_foreach (qof_book_get_collection (be->book(), GNC_ID_LOT),
(QofInstanceForeachCB)do_save_lot, &data);
return data.is_ok;
}
@@ -203,7 +203,7 @@ GncSqlColumnTableEntryImpl<CT_LOTREF>::load (const GncSqlBackend* be,
{
load_from_guid_ref(row, obj_name, pObject,
[be](GncGUID* g){
- return gnc_lot_lookup(g, be->book);
+ return gnc_lot_lookup(g, be->book());
});
}
diff --git a/src/backend/sql/gnc-order-sql.cpp b/src/backend/sql/gnc-order-sql.cpp
index f330f3e..8541bbe 100644
--- a/src/backend/sql/gnc-order-sql.cpp
+++ b/src/backend/sql/gnc-order-sql.cpp
@@ -89,10 +89,10 @@ load_single_order (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
guid = gnc_sql_load_guid (be, row);
- pOrder = gncOrderLookup (be->book, guid);
+ pOrder = gncOrderLookup (be->book(), guid);
if (pOrder == NULL)
{
- pOrder = gncOrderCreate (be->book);
+ pOrder = gncOrderCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_ORDER, pOrder, col_table);
qof_instance_mark_clean (QOF_INSTANCE (pOrder));
@@ -164,7 +164,7 @@ GncSqlOrderBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data{be, true, this};
- qof_object_foreach (GNC_ID_ORDER, be->book, write_single_order, &data);
+ qof_object_foreach (GNC_ID_ORDER, be->book(), write_single_order, &data);
return data.is_ok;
}
@@ -178,7 +178,7 @@ GncSqlColumnTableEntryImpl<CT_ORDERREF>::load (const GncSqlBackend* be,
{
load_from_guid_ref(row, obj_name, pObject,
[be](GncGUID* g){
- return gncOrderLookup(be->book, g);
+ return gncOrderLookup(be->book(), g);
});
}
diff --git a/src/backend/sql/gnc-owner-sql.cpp b/src/backend/sql/gnc-owner-sql.cpp
index 0e354f9..ca6b452 100644
--- a/src/backend/sql/gnc-owner-sql.cpp
+++ b/src/backend/sql/gnc-owner-sql.cpp
@@ -61,7 +61,7 @@ GncSqlColumnTableEntryImpl<CT_OWNERREF>::load (const GncSqlBackend* be,
g_return_if_fail (be != NULL);
g_return_if_fail (pObject != NULL);
- auto book = be->book;
+ auto book = be->book();
auto buf = std::string{m_col_name} + "_type";
try
{
diff --git a/src/backend/sql/gnc-price-sql.cpp b/src/backend/sql/gnc-price-sql.cpp
index 1fa67b8..7974eaf 100644
--- a/src/backend/sql/gnc-price-sql.cpp
+++ b/src/backend/sql/gnc-price-sql.cpp
@@ -89,7 +89,7 @@ load_single_price (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
- pPrice = gnc_price_create (be->book);
+ pPrice = gnc_price_create (be->book());
gnc_price_begin_edit (pPrice);
gnc_sql_load_object (be, row, GNC_ID_PRICE, pPrice, col_table);
@@ -106,7 +106,7 @@ GncSqlPriceBackend::load_all (GncSqlBackend* be)
g_return_if_fail (be != NULL);
- pBook = be->book;
+ pBook = be->book();
pPriceDB = gnc_pricedb_get_db (pBook);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
if (stmt != nullptr)
@@ -154,7 +154,7 @@ GncSqlPriceBackend::create_tables (GncSqlBackend* be)
{
/* Upgrade 64 bit int handling */
gnc_sql_upgrade_table (be, TABLE_NAME, col_table);
- (void)gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Prices table upgraded from version 1 to version %d\n", TABLE_VERSION);
}
@@ -179,7 +179,7 @@ GncSqlPriceBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -226,7 +226,7 @@ GncSqlPriceBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data{be, true, this};
- auto priceDB = gnc_pricedb_get_db (be->book);
+ auto priceDB = gnc_pricedb_get_db (be->book());
return gnc_pricedb_foreach_price (priceDB, write_price, &data, TRUE);
}
diff --git a/src/backend/sql/gnc-recurrence-sql.cpp b/src/backend/sql/gnc-recurrence-sql.cpp
index 10d1a81..7ca09ca 100644
--- a/src/backend/sql/gnc-recurrence-sql.cpp
+++ b/src/backend/sql/gnc-recurrence-sql.cpp
@@ -321,7 +321,7 @@ gnc_sql_set_recurrences_from_db (GncSqlBackend* be, const GncGUID* guid)
(void)guid_to_string_buff (guid, guid_buf);
buf = g_strdup_printf ("SELECT * FROM %s WHERE obj_guid='%s'", TABLE_NAME,
guid_buf);
- auto stmt = be->conn->create_statement_from_sql (buf);
+ auto stmt = be->create_statement_from_sql (buf);
g_free (buf);
auto result = gnc_sql_execute_select_statement (be, stmt);
return result;
@@ -424,7 +424,7 @@ GncSqlRecurrenceBackend::create_tables (GncSqlBackend* be)
{
upgrade_recurrence_table_1_2 (be);
}
- (void)gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Recurrence table upgraded from version %d to version %d\n", version,
TABLE_VERSION);
}
diff --git a/src/backend/sql/gnc-schedxaction-sql.cpp b/src/backend/sql/gnc-schedxaction-sql.cpp
index 2ed4002..3eb6e3c 100644
--- a/src/backend/sql/gnc-schedxaction-sql.cpp
+++ b/src/backend/sql/gnc-schedxaction-sql.cpp
@@ -104,7 +104,7 @@ load_single_sx (GncSqlBackend* be, GncSqlRow& row)
guid = gnc_sql_load_guid (be, row);
g_assert (guid != NULL);
- pSx = xaccSchedXactionMalloc (be->book);
+ pSx = xaccSchedXactionMalloc (be->book());
gnc_sx_begin_edit (pSx);
gnc_sql_load_object (be, row, GNC_SX_ID, pSx, col_table);
@@ -128,7 +128,7 @@ GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
auto result = gnc_sql_execute_select_statement (be, stmt);
SchedXactions* sxes;
GList* list = NULL;
- sxes = gnc_book_get_schedxactions (be->book);
+ sxes = gnc_book_get_schedxactions (be->book());
for (auto row : *result)
{
@@ -171,7 +171,7 @@ GncSqlSchedXactionBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index b87dfd6..c91f77c 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -714,7 +714,7 @@ gnc_sql_slots_save (GncSqlBackend* be, const GncGUID* guid, gboolean is_infant,
g_return_val_if_fail (pFrame != NULL, FALSE);
// If this is not saving into a new db, clear out the old saved slots first
- if (!be->is_pristine_db && !is_infant)
+ if (!be->pristine() && !is_infant)
{
(void)gnc_sql_slots_delete (be, guid);
}
@@ -947,7 +947,7 @@ load_slot_for_book_object (GncSqlBackend* be, GncSqlRow& row,
guid = load_obj_guid (be, row);
g_return_if_fail (guid != NULL);
- inst = lookup_fn (guid, be->book);
+ inst = lookup_fn (guid, be->book());
g_return_if_fail (inst != NULL);
slot_info.be = be;
@@ -1045,7 +1045,7 @@ GncSqlSlotsBackend::create_tables (GncSqlBackend* be)
PERR ("Unable to add gdate column\n");
}
}
- (void)gnc_sql_set_table_version (be, TABLE_NAME, TABLE_VERSION);
+ be->set_table_version (TABLE_NAME, TABLE_VERSION);
PINFO ("Slots table upgraded from version %d to version %d\n", version,
TABLE_VERSION);
}
diff --git a/src/backend/sql/gnc-tax-table-sql.cpp b/src/backend/sql/gnc-tax-table-sql.cpp
index 415f766..94d1f48 100644
--- a/src/backend/sql/gnc-tax-table-sql.cpp
+++ b/src/backend/sql/gnc-tax-table-sql.cpp
@@ -237,7 +237,7 @@ load_taxtable_entries (GncSqlBackend* be, GncTaxTable* tt)
g_value_set_string (&value, guid_buf);
buf = g_strdup_printf ("SELECT * FROM %s WHERE taxtable='%s'",
TTENTRIES_TABLE_NAME, guid_buf);
- auto stmt = be->conn->create_statement_from_sql (buf);
+ auto stmt = be->create_statement_from_sql (buf);
g_free (buf);
auto result = gnc_sql_execute_select_statement (be, stmt);
for (auto row : *result)
@@ -254,10 +254,10 @@ load_single_taxtable (GncSqlBackend* be, GncSqlRow& row,
g_return_if_fail (be != NULL);
guid = gnc_sql_load_guid (be, row);
- tt = gncTaxTableLookup (be->book, guid);
+ tt = gncTaxTableLookup (be->book(), guid);
if (tt == NULL)
{
- tt = gncTaxTableCreate (be->book);
+ tt = gncTaxTableCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_TAXTABLE, tt, tt_col_table);
gnc_sql_slots_load (be, QOF_INSTANCE (tt));
@@ -342,7 +342,7 @@ GncSqlTaxTableBackend::create_tables (GncSqlBackend* be)
{
/* Upgrade 64 bit int handling */
gnc_sql_upgrade_table (be, TT_TABLE_NAME, tt_col_table);
- gnc_sql_set_table_version (be, TT_TABLE_NAME, TT_TABLE_VERSION);
+ be->set_table_version (TT_TABLE_NAME, TT_TABLE_VERSION);
PINFO ("Taxtables table upgraded from version 1 to version %d\n",
TT_TABLE_VERSION);
}
@@ -357,7 +357,7 @@ GncSqlTaxTableBackend::create_tables (GncSqlBackend* be)
{
/* Upgrade 64 bit int handling */
gnc_sql_upgrade_table (be, TTENTRIES_TABLE_NAME, ttentries_col_table);
- gnc_sql_set_table_version (be, TTENTRIES_TABLE_NAME, TTENTRIES_TABLE_VERSION);
+ be->set_table_version (TTENTRIES_TABLE_NAME, TTENTRIES_TABLE_VERSION);
PINFO ("Taxtable entries table upgraded from version 1 to version %d\n",
TTENTRIES_TABLE_VERSION);
}
@@ -423,7 +423,7 @@ GncSqlTaxTableBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -477,7 +477,7 @@ GncSqlTaxTableBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data{be, true, this};
- qof_object_foreach (GNC_ID_TAXTABLE, be->book, save_next_taxtable, &data);
+ qof_object_foreach (GNC_ID_TAXTABLE, be->book(), save_next_taxtable, &data);
return data.is_ok;
}
@@ -491,7 +491,7 @@ GncSqlColumnTableEntryImpl<CT_TAXTABLEREF>::load (const GncSqlBackend* be,
{
load_from_guid_ref(row, obj_name, pObject,
[be](GncGUID* g){
- return gncTaxTableLookup(be->book, g);
+ return gncTaxTableLookup(be->book(), g);
});
}
diff --git a/src/backend/sql/gnc-transaction-sql.cpp b/src/backend/sql/gnc-transaction-sql.cpp
index f595eba..e1300ad 100644
--- a/src/backend/sql/gnc-transaction-sql.cpp
+++ b/src/backend/sql/gnc-transaction-sql.cpp
@@ -231,12 +231,12 @@ load_single_split (GncSqlBackend* be, GncSqlRow& row)
else
{
split_guid = *guid;
- pSplit = xaccSplitLookup (&split_guid, be->book);
+ pSplit = xaccSplitLookup (&split_guid, be->book());
}
if (pSplit == NULL)
{
- pSplit = xaccMallocSplit (be->book);
+ pSplit = xaccMallocSplit (be->book());
}
/* If the split is dirty, don't overwrite it */
@@ -246,12 +246,12 @@ load_single_split (GncSqlBackend* be, GncSqlRow& row)
}
/*# -ifempty */
- if (pSplit != xaccSplitLookup (&split_guid, be->book))
+ if (pSplit != xaccSplitLookup (&split_guid, be->book()))
{
gchar guidstr[GUID_ENCODING_LENGTH + 1];
guid_to_string_buff (qof_instance_get_guid (pSplit), guidstr);
PERR ("A malformed split with id %s was found in the dataset.", guidstr);
- qof_backend_set_error (&be->be, ERR_BACKEND_DATA_CORRUPT);
+ qof_backend_set_error ((QofBackend*)be, ERR_BACKEND_DATA_CORRUPT);
pSplit = NULL;
}
return pSplit;
@@ -308,22 +308,22 @@ load_single_tx (GncSqlBackend* be, GncSqlRow& row)
tx_guid = *guid;
// Don't overwrite the transaction if it's already been loaded (and possibly modified).
- pTx = xaccTransLookup (&tx_guid, be->book);
+ pTx = xaccTransLookup (&tx_guid, be->book());
if (pTx != NULL)
{
return NULL;
}
- pTx = xaccMallocTransaction (be->book);
+ pTx = xaccMallocTransaction (be->book());
xaccTransBeginEdit (pTx);
gnc_sql_load_object (be, row, GNC_ID_TRANS, pTx, tx_col_table);
- if (pTx != xaccTransLookup (&tx_guid, be->book))
+ if (pTx != xaccTransLookup (&tx_guid, be->book()))
{
gchar guidstr[GUID_ENCODING_LENGTH + 1];
guid_to_string_buff (qof_instance_get_guid (pTx), guidstr);
PERR ("A malformed transaction with id %s was found in the dataset.", guidstr);
- qof_backend_set_error (&be->be, ERR_BACKEND_DATA_CORRUPT);
+ qof_backend_set_error ((QofBackend*)be, ERR_BACKEND_DATA_CORRUPT);
pTx = NULL;
}
@@ -370,7 +370,7 @@ query_transactions (GncSqlBackend* be, const GncSqlStatementPtr& stmt)
#if LOAD_TRANSACTIONS_AS_NEEDED
GSList* bal_list = NULL;
GSList* nextbal;
- Account* root = gnc_book_get_root_account (be->book);
+ Account* root = gnc_book_get_root_account (be->book());
qof_event_suspend ();
xaccAccountBeginEdit (root);
@@ -506,7 +506,7 @@ GncSqlTransBackend::create_tables (GncSqlBackend* be)
2->3: allow dates to be NULL
*/
gnc_sql_upgrade_table (be, m_table_name.c_str(), tx_col_table);
- (void)gnc_sql_set_table_version (be, m_table_name.c_str(), m_version);
+ be->set_table_version (m_table_name.c_str(), m_version);
PINFO ("Transactions table upgraded from version %d to version %d\n",
version, m_version);
}
@@ -544,7 +544,7 @@ GncSqlSplitBackend::create_tables (GncSqlBackend* be)
m_table_name.c_str(),
account_guid_col_table))
PERR ("Unable to create index\n");
- (void)gnc_sql_set_table_version (be, m_table_name.c_str(), m_version);
+ be->set_table_version (m_table_name.c_str(), m_version);
PINFO ("Splits table upgraded from version %d to version %d\n", version,
m_version);
}
@@ -625,7 +625,7 @@ GncSqlSplitBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -668,7 +668,7 @@ GncSqlTransBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -685,7 +685,7 @@ GncSqlTransBackend::commit (GncSqlBackend* be, QofInstance* inst)
if (! is_ok)
{
err = "Commodity save failed: Probably an invalid or missing currency";
- qof_backend_set_error (&be->be, ERR_BACKEND_DATA_CORRUPT);
+ qof_backend_set_error ((QofBackend*)be, ERR_BACKEND_DATA_CORRUPT);
}
}
@@ -1238,7 +1238,7 @@ set_acct_bal_account_from_guid (gpointer pObject, gpointer pValue)
g_return_if_fail (pObject != NULL);
g_return_if_fail (pValue != NULL);
- bal->acct = xaccAccountLookup (guid, bal->be->book);
+ bal->acct = xaccAccountLookup (guid, bal->be->book());
}
static void
@@ -1389,7 +1389,7 @@ GncSqlColumnTableEntryImpl<CT_TXREF>::load (const GncSqlBackend* be,
auto val = row.get_string_at_col (m_col_name);
GncGUID guid;
(void)string_to_guid (val.c_str(), &guid);
- auto tx = xaccTransLookup (&guid, be->book);
+ auto tx = xaccTransLookup (&guid, be->book());
// If the transaction is not found, try loading it
if (tx == nullptr)
@@ -1399,7 +1399,7 @@ GncSqlColumnTableEntryImpl<CT_TXREF>::load (const GncSqlBackend* be,
auto stmt = gnc_sql_create_statement_from_sql ((GncSqlBackend*)be,
buf.c_str());
query_transactions ((GncSqlBackend*)be, stmt);
- tx = xaccTransLookup (&guid, be->book);
+ tx = xaccTransLookup (&guid, be->book());
}
if (tx != nullptr)
diff --git a/src/backend/sql/gnc-vendor-sql.cpp b/src/backend/sql/gnc-vendor-sql.cpp
index 3c40be7..6ee5035 100644
--- a/src/backend/sql/gnc-vendor-sql.cpp
+++ b/src/backend/sql/gnc-vendor-sql.cpp
@@ -99,10 +99,10 @@ load_single_vendor (GncSqlBackend* be, GncSqlRow& row)
g_return_val_if_fail (be != NULL, NULL);
guid = gnc_sql_load_guid (be, row);
- pVendor = gncVendorLookup (be->book, guid);
+ pVendor = gncVendorLookup (be->book(), guid);
if (pVendor == NULL)
{
- pVendor = gncVendorCreate (be->book);
+ pVendor = gncVendorCreate (be->book());
}
gnc_sql_load_object (be, row, GNC_ID_VENDOR, pVendor, col_table);
qof_instance_mark_clean (QOF_INSTANCE (pVendor));
@@ -154,7 +154,7 @@ GncSqlVendorBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
op = OP_DB_DELETE;
}
- else if (be->is_pristine_db || is_infant)
+ else if (be->pristine() || is_infant)
{
op = OP_DB_INSERT;
}
@@ -229,7 +229,7 @@ GncSqlVendorBackend::write (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
write_objects_t data{be, true, this};
- qof_object_foreach (GNC_ID_VENDOR, be->book, write_single_vendor, &data);
+ qof_object_foreach (GNC_ID_VENDOR, be->book(), write_single_vendor, &data);
return data.is_ok;
}
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index 46bec74..d83eb50 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -105,6 +105,9 @@ public:
virtual std::string quote_string (const std::string& str)
const noexcept override { return std::string{str}; }
int dberror() const noexcept override { return 0; }
+ void set_error(int error, int repeat, bool retry) noexcept override { return; }
+ bool verify() noexcept override { return true; }
+ bool retry_connection(const char* msg) noexcept override { return true; }
private:
GncMockSqlResult m_result;
};
@@ -256,7 +259,6 @@ test_dirty_cb (QofBook* book, gboolean dirty, gpointer data)
static void
test_gnc_sql_commit_edit (void)
{
- GncSqlBackend be;
QofInstance* inst;
guint dirty_called = 0;
GncMockSqlConnection conn;
@@ -282,52 +284,51 @@ test_gnc_sql_commit_edit (void)
g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_handler, NULL);
qof_object_initialize ();
- be.book = qof_book_new ();
- be.conn = &conn;
+ auto book = qof_book_new();
+ GncSqlBackend be (&conn, book);
inst = static_cast<decltype (inst)> (g_object_new (QOF_TYPE_INSTANCE, NULL));
- qof_instance_init_data (inst, QOF_ID_NULL, be.book);
- be.loading = FALSE;
- qof_book_set_dirty_cb (be.book, test_dirty_cb, &dirty_called);
+ qof_instance_init_data (inst, QOF_ID_NULL, book);
+ qof_book_set_dirty_cb (book, test_dirty_cb, &dirty_called);
qof_instance_set_dirty_flag (inst, TRUE);
- qof_book_mark_session_dirty (be.book);
+ qof_book_mark_session_dirty (book);
g_assert (qof_instance_get_dirty_flag (inst));
- g_assert (qof_book_session_not_saved (be.book));
+ g_assert (qof_book_session_not_saved (book));
g_assert_cmpint (dirty_called, == , 1);
gnc_sql_commit_edit (&be, inst);
g_assert (!qof_instance_get_dirty_flag (inst));
- g_assert (!qof_book_session_not_saved (be.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, == , 0);
- qof_book_mark_session_dirty (be.book);
+ qof_book_mark_session_dirty (book);
- g_assert (!qof_instance_get_dirty_flag (QOF_INSTANCE (be.book)));
- g_assert (qof_book_session_not_saved (be.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 (&be, QOF_INSTANCE (be.book));
- g_assert (!qof_instance_get_dirty_flag (QOF_INSTANCE (be.book)));
- g_assert (qof_book_session_not_saved (be.book));
+ gnc_sql_commit_edit (&be, 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 (be.book), TRUE);
+ qof_instance_set_dirty_flag (QOF_INSTANCE (book), TRUE);
- g_assert (qof_instance_get_dirty_flag (QOF_INSTANCE (be.book)));
- g_assert (qof_book_session_not_saved (be.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 (&be, QOF_INSTANCE (be.book));
- g_assert (!qof_instance_get_dirty_flag (QOF_INSTANCE (be.book)));
- g_assert (!qof_book_session_not_saved (be.book));
+ gnc_sql_commit_edit (&be, 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);
- g_object_unref (be.book);
+ g_object_unref (book);
}
/* handle_and_term
static void
@@ -633,14 +634,7 @@ gnc_sql_convert_timespec_to_string (const GncSqlBackend* be, Timespec ts)// C: 1
static void
test_gnc_sql_convert_timespec_to_string ()
{
- GncSqlBackend be = {{
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, ERR_BACKEND_NO_ERR, nullptr,
- 0, nullptr
- },
- nullptr, nullptr, FALSE, FALSE, FALSE, nullptr,
- "%4d-%02d-%02d %02d:%02d:%02d"
- };
+ GncSqlBackend be {nullptr, nullptr, "%4d-%02d-%02d %02d:%02d:%02d"};
const char* date[numtests] = {"1995-03-11 19:17:26",
"2001-04-20 11:44:07",
"1964-02-29 09:15:23",
commit d1063463163645ba3c55fdf72bd4c1807e34843b
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jul 18 15:28:37 2016 -0700
Minimally document GncDbiResult.
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index bc97d76..bbfabb6 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -175,7 +175,9 @@ std::string add_columns_ddl(const GncSqlConnection* conn,
/* external access required for tests */
std::string adjust_sql_options_string(const std::string&);
-
+/**
+ * An iterable wrapper for dbi_result; allows using C++11 range for.
+ */
class GncDbiSqlResult : public GncSqlResult
{
public:
commit 97b6e3a6c6cf0c7389e120cae2d47e926293408c
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jul 18 15:28:08 2016 -0700
Pass ownership of the dbi_conn to GncDbiSqlConnection.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 13dc291..02c736b 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -1373,7 +1373,6 @@ gnc_dbi_session_end (QofBackend* be_start)
if (be->conn != nullptr)
{
gnc_dbi_unlock (be_start);
- dbi_conn_close (be->conn);
be->conn = nullptr;
}
if (be->sql_be.conn != nullptr)
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index a357bf0..bc97d76 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -92,7 +92,7 @@ public:
dbi_conn conn) :
m_qbe{qbe}, m_conn{conn}, m_provider{provider}, m_conn_ok{true},
m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0}, m_retry{false} {}
- ~GncDbiSqlConnection() override { delete m_provider; };
+ ~GncDbiSqlConnection() override;
GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
noexcept override;
int execute_nonselect_statement (const GncSqlStatementPtr&)
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
index e95e26f..aaa33fe 100644
--- a/src/backend/dbi/gnc-dbisqlconnection.cpp
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -71,6 +71,16 @@ GncDbiSqlStatement::add_where_cond(QofIdTypeConst type_name,
}
}
+GncDbiSqlConnection::~GncDbiSqlConnection()
+{
+ if (m_conn)
+ {
+ dbi_conn_close(m_conn);
+ m_conn = nullptr;
+ }
+ delete m_provider;
+}
+
GncSqlResultPtr
GncDbiSqlConnection::execute_select_statement (const GncSqlStatementPtr& stmt)
noexcept
commit e0d5cc5b0bb0020e9f61eca12de425028a2679fc
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jul 18 15:11:35 2016 -0700
New function GncSqlConnection::dberror().
GncDbiSqlResult::dberror() just calls it instead of retrieving the dbi_conn
to call dbi_conn_error() itself.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 087266f..13dc291 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -2044,12 +2044,6 @@ GncDbiSqlResult::begin()
return m_sentinel;
}
-int
-GncDbiSqlResult::dberror()
-{
- return dbi_conn_error(m_conn->conn(), nullptr);
-}
-
uint64_t
GncDbiSqlResult::size() const noexcept
{
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index c3c2f12..a357bf0 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -109,6 +109,8 @@ public:
bool add_columns_to_table (const std::string&, const ColVec&)
const noexcept override;
std::string quote_string (const std::string&) const noexcept override;
+ int dberror() const noexcept override {
+ return dbi_conn_error(m_conn, nullptr); }
QofBackend* qbe () const noexcept { return m_qbe; }
dbi_conn conn() const noexcept { return m_conn; }
GncDbiProvider* provider() { return m_provider; }
@@ -181,8 +183,8 @@ public:
m_conn{conn}, m_dbi_result{result}, m_iter{this}, m_row{&m_iter},
m_sentinel{nullptr} {}
~GncDbiSqlResult();
- int dberror();
uint64_t size() const noexcept;
+ int dberror() { return m_conn->dberror(); }
GncSqlRow& begin();
GncSqlRow& end() { return m_sentinel; }
protected:
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 0a79551..734cbb7 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -188,6 +188,10 @@ public:
const noexcept = 0;
virtual std::string quote_string (const std::string&)
const noexcept = 0;
+ /** Get the connection error value.
+ * If not 0 will normally be meaningless outside of implementation code.
+ */
+ virtual int dberror() const noexcept = 0;
};
/**
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index 509af0e..46bec74 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -104,6 +104,7 @@ public:
const noexcept override { return false; }
virtual std::string quote_string (const std::string& str)
const noexcept override { return std::string{str}; }
+ int dberror() const noexcept override { return 0; }
private:
GncMockSqlResult m_result;
};
commit 583c951adcab34f74447b41e5f9a886ba053bc15
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jul 18 15:04:41 2016 -0700
Use the right include delineators, it's not in the current source dir.
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index d07fe26..c3c2f12 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -26,7 +26,7 @@ extern "C"
{
#include <dbi/dbi.h>
}
-#include "gnc-backend-sql.h"
+#include <gnc-backend-sql.h>
/**
* Options to conn_table_operation
commit 5823bf0d9ab327ce7725649f7fcc0a3d9f11f4b8
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jul 18 15:01:55 2016 -0700
Move GncDbiSqlConnection into a separate file.
The declaration stays in gnc-backend-dbi.h because the dependencies are
still a little too tangled to be able to separate it.
diff --git a/src/backend/dbi/CMakeLists.txt b/src/backend/dbi/CMakeLists.txt
index 711a65d..be5fc15 100644
--- a/src/backend/dbi/CMakeLists.txt
+++ b/src/backend/dbi/CMakeLists.txt
@@ -5,7 +5,7 @@ ADD_SUBDIRECTORY(test)
# Source file gncmod-backend-dbi.c does not appear to be use in Makefile.in, so not included here.
SET (backend_dbi_SOURCES
- gnc-backend-dbi.cpp
+ gnc-backend-dbi.cpp gnc-dbisqlconnection.cpp
)
SET (backend_dbi_noinst_HEADERS
gnc-backend-dbi.h gnc-backend-dbi.hpp
diff --git a/src/backend/dbi/Makefile.am b/src/backend/dbi/Makefile.am
index ac07b8d..a2a2baa 100644
--- a/src/backend/dbi/Makefile.am
+++ b/src/backend/dbi/Makefile.am
@@ -21,7 +21,8 @@ AM_CPPFLAGS = \
${WARN_CFLAGS}
libgncmod_backend_dbi_la_SOURCES = \
- gnc-backend-dbi.cpp
+ gnc-backend-dbi.cpp \
+ gnc-dbisqlconnection.cpp
noinst_HEADERS = \
gnc-backend-dbi.h \
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 8f559d9..087266f 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -125,13 +125,8 @@ static gboolean gnc_dbi_lock_database (QofBackend *qbe, gboolean ignore_lock);
static void gnc_dbi_unlock (QofBackend *qbe);
static gboolean save_may_clobber_data (QofBackend* qbe);
-static std::string create_index_ddl (const GncSqlConnection* conn,
- const std::string& index_name,
- const std::string& table_name,
- const EntryVec& col_table);
static GncDbiTestResult conn_test_dbi_library (dbi_conn conn);
-#define DBI_MAX_CONN_ATTEMPTS 5
enum class DbType
{
DBI_SQLITE,
@@ -170,57 +165,6 @@ public:
};
/* ================================================================= */
-
-/* Check if the dbi connection is valid. If not attempt to re-establish it
- * Returns TRUE is there is a valid connection in the end or FALSE otherwise
- */
-bool
-GncDbiSqlConnection::verify () noexcept
-{
- if (m_conn_ok)
- return true;
-
- /* We attempt to connect only once here. The error function will
- * automatically re-attempt up until DBI_MAX_CONN_ATTEMPTS time to connect
- * if this call fails. After all these attempts, conn_ok will indicate if
- * there is a valid connection or not.
- */
- init_error ();
- m_conn_ok = true;
- (void)dbi_conn_connect (m_conn);
-
- return m_conn_ok;
-}
-
-bool
-GncDbiSqlConnection::retry_connection(const char* msg)
- noexcept
-{
- while (m_retry && m_error_repeat <= DBI_MAX_CONN_ATTEMPTS)
- {
- m_conn_ok = false;
- if (dbi_conn_connect(m_conn) == 0)
- {
- init_error();
- m_conn_ok = true;
- return true;
- }
-#ifdef G_OS_WIN32
- const guint backoff_msecs = 1;
- Sleep (backoff_msecs * 2 << ++m_error_repeat);
-#else
- const guint backoff_usecs = 1000;
- usleep (backoff_usecs * 2 << ++m_error_repeat);
-#endif
- PINFO ("DBI error: %s - Reconnecting...\n", msg);
-
- }
- PERR ("DBI error: %s - Giving up after %d consecutive attempts.\n", msg,
- DBI_MAX_CONN_ATTEMPTS);
- m_conn_ok = false;
- return false;
-}
-
/* ================================================================= */
static void
@@ -1103,10 +1047,8 @@ GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
template<> void
GncDbiProviderImpl<DbType::DBI_MYSQL>::drop_index (dbi_conn conn, const std::string& index)
{
- unsigned int sep{0}, count{0};
- while ((sep = index.find(' ', sep)) != std::string::npos)
- ++count;
- if (count != 1)
+ auto sep = index.find(' ', 0);
+ if (index.find(' ', sep + 1) != std::string::npos)
{
PWARN("Drop index error: invalid MySQL index format (<index> <table>): %s",
index.c_str());
@@ -1536,33 +1478,6 @@ save_may_clobber_data (QofBackend* qbe)
return retval;
}
-dbi_result
-GncDbiSqlConnection::table_manage_backup (const std::string& table_name,
- TableOpType op)
-{
- auto new_name = table_name + "_back";
- dbi_result result = nullptr;
- switch (op)
- {
- case backup:
- result = dbi_conn_queryf (m_conn, "ALTER TABLE %s RENAME TO %s",
- table_name.c_str(), new_name.c_str());
- break;
- case rollback:
- result = dbi_conn_queryf (m_conn,
- "ALTER TABLE %s RENAME TO %s",
- new_name.c_str(), table_name.c_str());
- break;
- case drop_backup:
- result = dbi_conn_queryf (m_conn, "DROP TABLE %s",
- new_name.c_str());
- break;
- default:
- break;
- }
- return result;
-}
-
/**
* Perform a specified SQL operation on every table in a
* database. Possible operations are:
@@ -2142,215 +2057,6 @@ GncDbiSqlResult::size() const noexcept
}
/* --------------------------------------------------------- */
-class GncDbiSqlStatement : public GncSqlStatement
-{
-public:
- GncDbiSqlStatement(const GncSqlConnection* conn, const std::string& sql) :
- m_conn{conn}, m_sql {sql} {}
- ~GncDbiSqlStatement() {}
- const char* to_sql() const override;
- void add_where_cond(QofIdTypeConst, const PairVec&) override;
-
-private:
- const GncSqlConnection* m_conn;
- std::string m_sql;
-};
-
-
-const char*
-GncDbiSqlStatement::to_sql() const
-{
- return m_sql.c_str();
-}
-
-void
-GncDbiSqlStatement::add_where_cond(QofIdTypeConst type_name,
- const PairVec& col_values)
-{
- m_sql += " WHERE ";
- for (auto colpair : col_values)
- {
- if (colpair != *col_values.begin())
- m_sql += " AND ";
- m_sql += colpair.first + " = " +
- m_conn->quote_string (colpair.second.c_str());
- }
-}
-
-/* --------------------------------------------------------- */
-GncSqlResultPtr
-GncDbiSqlConnection::execute_select_statement (const GncSqlStatementPtr& stmt)
- noexcept
-{
- dbi_result result;
-
- DEBUG ("SQL: %s\n", stmt->to_sql());
- gnc_push_locale (LC_NUMERIC, "C");
- do
- {
- init_error ();
- result = dbi_conn_query (m_conn, stmt->to_sql());
- }
- while (m_retry);
- if (result == nullptr)
- PERR ("Error executing SQL %s\n", stmt->to_sql());
- gnc_pop_locale (LC_NUMERIC);
- return GncSqlResultPtr(new GncDbiSqlResult (this, result));
-}
-
-int
-GncDbiSqlConnection::execute_nonselect_statement (const GncSqlStatementPtr& stmt)
- noexcept
-{
- dbi_result result;
-
- DEBUG ("SQL: %s\n", stmt->to_sql());
- do
- {
- init_error ();
- result = dbi_conn_query (m_conn, stmt->to_sql());
- }
- while (m_retry);
- if (result == nullptr && m_last_error)
- {
- PERR ("Error executing SQL %s\n", stmt->to_sql());
- return -1;
- }
- if (!result)
- return 0;
- auto num_rows = (gint)dbi_result_get_numrows_affected (result);
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
- return num_rows;
-}
-
-GncSqlStatementPtr
-GncDbiSqlConnection::create_statement_from_sql (const std::string& sql)
- const noexcept
-{
- return std::unique_ptr<GncSqlStatement>{new GncDbiSqlStatement (this, sql)};
-}
-
-bool
-GncDbiSqlConnection::does_table_exist (const std::string& table_name)
- const noexcept
-{
- auto dbname = dbi_conn_get_option (m_conn, "dbname");
- auto tables = dbi_conn_get_table_list (m_conn, dbname, table_name.c_str());
- auto nTables = dbi_result_get_numrows (tables);
- auto status = dbi_result_free (tables);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
-
- return nTables == 1;
-}
-
-bool
-GncDbiSqlConnection::begin_transaction () noexcept
-{
- dbi_result result;
-
- DEBUG ("BEGIN\n");
-
- if (!verify ())
- {
- PERR ("gnc_dbi_verify_conn() failed\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- return FALSE;
- }
-
- do
- {
- init_error ();
- result = dbi_conn_queryf (m_conn, "BEGIN");
- }
- while (m_retry);
-
- auto success = (result != nullptr);
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
- if (!success)
- {
- PERR ("BEGIN transaction failed()\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
-
- return success;
-}
-
-bool
-GncDbiSqlConnection::rollback_transaction () const noexcept
-{
- DEBUG ("ROLLBACK\n");
- const char* command = "ROLLBACK";
- auto result = dbi_conn_query (m_conn, command);
- auto success = (result != nullptr);
-
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
- if (!success)
- {
- PERR ("Error in conn_rollback_transaction()\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
-
- return success;
-}
-
-bool
-GncDbiSqlConnection::commit_transaction () const noexcept
-{
- DEBUG ("COMMIT\n");
- auto result = dbi_conn_queryf (m_conn, "COMMIT");
- auto success = (result != nullptr);
-
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
- if (!success)
- {
- PERR ("Error in conn_commit_transaction()\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
-
- return success;
-}
-
-static std::string
-create_index_ddl (const GncSqlConnection* conn, const std::string& index_name,
- const std::string& table_name, const EntryVec& col_table)
-{
- std::string ddl;
- ddl += "CREATE INDEX " + index_name + " ON " + table_name + "(";
- for (auto const table_row : col_table)
- {
- if (table_row != *col_table.begin())
- {
- ddl =+ ", ";
- }
- ddl += table_row->name();
- }
- ddl += ")";
- return ddl;
-}
std::string
add_columns_ddl(const GncSqlConnection* conn,
@@ -2482,7 +2188,7 @@ GncDbiProviderImpl<DbType::DBI_MYSQL>::append_col_def (std::string& ddl,
ddl += info.m_name + " " + type_name;
if (info.m_size != 0 && info.m_type == BCT_STRING)
{
- ddl += std::to_string(info.m_size);
+ ddl += "(" + std::to_string(info.m_size) + ")";
}
if (info.m_unicode)
{
@@ -2561,86 +2267,6 @@ GncDbiProviderImpl<DbType::DBI_PGSQL>::append_col_def (std::string& ddl,
}
}
-bool
-GncDbiSqlConnection::create_table (const std::string& table_name,
- const ColVec& info_vec) const noexcept
-{
- auto ddl = m_provider->create_table_ddl(this, table_name, info_vec);
- if (ddl.empty())
- return false;
-
- DEBUG ("SQL: %s\n", ddl.c_str());
- auto result = dbi_conn_query (m_conn, ddl.c_str());
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
-
- return true;
-}
-
-bool
-GncDbiSqlConnection::create_index(const std::string& index_name,
- const std::string& table_name,
- const EntryVec& col_table) const noexcept
-{
- auto ddl = create_index_ddl (this, index_name, table_name, col_table);
- if (ddl.empty())
- return false;
- DEBUG ("SQL: %s\n", ddl.c_str());
- auto result = dbi_conn_query (m_conn, ddl.c_str());
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
-
- return true;
-}
-
-bool
-GncDbiSqlConnection::add_columns_to_table(const std::string& table_name,
- const ColVec& info_vec)
- const noexcept
-{
- auto ddl = add_columns_ddl(this, table_name, info_vec);
- if (ddl.empty())
- return false;
-
- DEBUG ("SQL: %s\n", ddl.c_str());
- auto result = dbi_conn_query (m_conn, ddl.c_str());
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR( "Error in dbi_result_free() result\n" );
- qof_backend_set_error(m_qbe, ERR_BACKEND_SERVER_ERR );
- }
-
- return true;
-}
-
-std::string
-GncDbiSqlConnection::quote_string (const std::string& unquoted_str)
- const noexcept
-{
- gchar* quoted_str;
- size_t size;
-
- size = dbi_conn_quote_string_copy (m_conn, unquoted_str.c_str(),
- "ed_str);
- if (size != 0)
- {
- return std::string{quoted_str};
- }
- else
- {
- return std::string{""};
- }
-}
-
static std::vector<std::string>
conn_get_table_list (dbi_conn conn, const std::string& dbname)
{
diff --git a/src/backend/dbi/gnc-dbisqlconnection.cpp b/src/backend/dbi/gnc-dbisqlconnection.cpp
new file mode 100644
index 0000000..e95e26f
--- /dev/null
+++ b/src/backend/dbi/gnc-dbisqlconnection.cpp
@@ -0,0 +1,405 @@
+/********************************************************************
+ * gnc-dbisqlconnection.cpp: Encapsulate libdbi dbi_conn *
+ * *
+ * Copyright 2016 John Ralls <jralls at ceridwen.us> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+
+#include <guid.hpp>
+extern "C"
+{
+#include <config.h>
+#include <platform.h>
+#include <gnc-locale-utils.h>
+}
+#include "gnc-backend-dbi.hpp"
+
+static QofLogModule log_module = G_LOG_DOMAIN;
+
+static const unsigned int DBI_MAX_CONN_ATTEMPTS = 5;
+
+
+/* --------------------------------------------------------- */
+class GncDbiSqlStatement : public GncSqlStatement
+{
+public:
+ GncDbiSqlStatement(const GncSqlConnection* conn, const std::string& sql) :
+ m_conn{conn}, m_sql {sql} {}
+ ~GncDbiSqlStatement() {}
+ const char* to_sql() const override;
+ void add_where_cond(QofIdTypeConst, const PairVec&) override;
+
+private:
+ const GncSqlConnection* m_conn;
+ std::string m_sql;
+};
+
+
+const char*
+GncDbiSqlStatement::to_sql() const
+{
+ return m_sql.c_str();
+}
+
+void
+GncDbiSqlStatement::add_where_cond(QofIdTypeConst type_name,
+ const PairVec& col_values)
+{
+ m_sql += " WHERE ";
+ for (auto colpair : col_values)
+ {
+ if (colpair != *col_values.begin())
+ m_sql += " AND ";
+ m_sql += colpair.first + " = " +
+ m_conn->quote_string (colpair.second.c_str());
+ }
+}
+
+GncSqlResultPtr
+GncDbiSqlConnection::execute_select_statement (const GncSqlStatementPtr& stmt)
+ noexcept
+{
+ dbi_result result;
+
+ DEBUG ("SQL: %s\n", stmt->to_sql());
+ gnc_push_locale (LC_NUMERIC, "C");
+ do
+ {
+ init_error ();
+ result = dbi_conn_query (m_conn, stmt->to_sql());
+ }
+ while (m_retry);
+ if (result == nullptr)
+ PERR ("Error executing SQL %s\n", stmt->to_sql());
+ gnc_pop_locale (LC_NUMERIC);
+ return GncSqlResultPtr(new GncDbiSqlResult (this, result));
+}
+
+int
+GncDbiSqlConnection::execute_nonselect_statement (const GncSqlStatementPtr& stmt)
+ noexcept
+{
+ dbi_result result;
+
+ DEBUG ("SQL: %s\n", stmt->to_sql());
+ do
+ {
+ init_error ();
+ result = dbi_conn_query (m_conn, stmt->to_sql());
+ }
+ while (m_retry);
+ if (result == nullptr && m_last_error)
+ {
+ PERR ("Error executing SQL %s\n", stmt->to_sql());
+ return -1;
+ }
+ if (!result)
+ return 0;
+ auto num_rows = (gint)dbi_result_get_numrows_affected (result);
+ auto status = dbi_result_free (result);
+ if (status < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+ return num_rows;
+}
+
+GncSqlStatementPtr
+GncDbiSqlConnection::create_statement_from_sql (const std::string& sql)
+ const noexcept
+{
+ return std::unique_ptr<GncSqlStatement>{new GncDbiSqlStatement (this, sql)};
+}
+
+bool
+GncDbiSqlConnection::does_table_exist (const std::string& table_name)
+ const noexcept
+{
+ auto dbname = dbi_conn_get_option (m_conn, "dbname");
+ auto tables = dbi_conn_get_table_list (m_conn, dbname, table_name.c_str());
+ auto nTables = dbi_result_get_numrows (tables);
+ auto status = dbi_result_free (tables);
+ if (status < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+
+ return nTables == 1;
+}
+
+bool
+GncDbiSqlConnection::begin_transaction () noexcept
+{
+ dbi_result result;
+
+ DEBUG ("BEGIN\n");
+
+ if (!verify ())
+ {
+ PERR ("gnc_dbi_verify_conn() failed\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ return FALSE;
+ }
+
+ do
+ {
+ init_error ();
+ result = dbi_conn_queryf (m_conn, "BEGIN");
+ }
+ while (m_retry);
+
+ auto success = (result != nullptr);
+ auto status = dbi_result_free (result);
+ if (status < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+ if (!success)
+ {
+ PERR ("BEGIN transaction failed()\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+
+ return success;
+}
+
+bool
+GncDbiSqlConnection::rollback_transaction () const noexcept
+{
+ DEBUG ("ROLLBACK\n");
+ const char* command = "ROLLBACK";
+ auto result = dbi_conn_query (m_conn, command);
+ auto success = (result != nullptr);
+
+ auto status = dbi_result_free (result);
+ if (status < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+ if (!success)
+ {
+ PERR ("Error in conn_rollback_transaction()\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+
+ return success;
+}
+
+bool
+GncDbiSqlConnection::commit_transaction () const noexcept
+{
+ DEBUG ("COMMIT\n");
+ auto result = dbi_conn_queryf (m_conn, "COMMIT");
+ auto success = (result != nullptr);
+
+ auto status = dbi_result_free (result);
+ if (status < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+ if (!success)
+ {
+ PERR ("Error in conn_commit_transaction()\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+
+ return success;
+}
+
+
+bool
+GncDbiSqlConnection::create_table (const std::string& table_name,
+ const ColVec& info_vec) const noexcept
+{
+ auto ddl = m_provider->create_table_ddl(this, table_name, info_vec);
+ if (ddl.empty())
+ return false;
+
+ DEBUG ("SQL: %s\n", ddl.c_str());
+ auto result = dbi_conn_query (m_conn, ddl.c_str());
+ auto status = dbi_result_free (result);
+ if (status < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+
+ return true;
+}
+
+static std::string
+create_index_ddl (const GncSqlConnection* conn, const std::string& index_name,
+ const std::string& table_name, const EntryVec& col_table)
+{
+ std::string ddl;
+ ddl += "CREATE INDEX " + index_name + " ON " + table_name + "(";
+ for (auto const table_row : col_table)
+ {
+ if (table_row != *col_table.begin())
+ {
+ ddl =+ ", ";
+ }
+ ddl += table_row->name();
+ }
+ ddl += ")";
+ return ddl;
+}
+
+bool
+GncDbiSqlConnection::create_index(const std::string& index_name,
+ const std::string& table_name,
+ const EntryVec& col_table) const noexcept
+{
+ auto ddl = create_index_ddl (this, index_name, table_name, col_table);
+ if (ddl.empty())
+ return false;
+ DEBUG ("SQL: %s\n", ddl.c_str());
+ auto result = dbi_conn_query (m_conn, ddl.c_str());
+ auto status = dbi_result_free (result);
+ if (status < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
+ }
+
+ return true;
+}
+
+bool
+GncDbiSqlConnection::add_columns_to_table(const std::string& table_name,
+ const ColVec& info_vec)
+ const noexcept
+{
+ auto ddl = add_columns_ddl(this, table_name, info_vec);
+ if (ddl.empty())
+ return false;
+
+ DEBUG ("SQL: %s\n", ddl.c_str());
+ auto result = dbi_conn_query (m_conn, ddl.c_str());
+ auto status = dbi_result_free (result);
+ if (status < 0)
+ {
+ PERR( "Error in dbi_result_free() result\n" );
+ qof_backend_set_error(m_qbe, ERR_BACKEND_SERVER_ERR );
+ }
+
+ return true;
+}
+
+std::string
+GncDbiSqlConnection::quote_string (const std::string& unquoted_str)
+ const noexcept
+{
+ gchar* quoted_str;
+ size_t size;
+
+ size = dbi_conn_quote_string_copy (m_conn, unquoted_str.c_str(),
+ "ed_str);
+ if (size != 0)
+ {
+ return std::string{quoted_str};
+ }
+ else
+ {
+ return std::string{""};
+ }
+}
+
+/* Check if the dbi connection is valid. If not attempt to re-establish it
+ * Returns TRUE is there is a valid connection in the end or FALSE otherwise
+ */
+bool
+GncDbiSqlConnection::verify () noexcept
+{
+ if (m_conn_ok)
+ return true;
+
+ /* We attempt to connect only once here. The error function will
+ * automatically re-attempt up until DBI_MAX_CONN_ATTEMPTS time to connect
+ * if this call fails. After all these attempts, conn_ok will indicate if
+ * there is a valid connection or not.
+ */
+ init_error ();
+ m_conn_ok = true;
+ (void)dbi_conn_connect (m_conn);
+
+ return m_conn_ok;
+}
+
+bool
+GncDbiSqlConnection::retry_connection(const char* msg)
+ noexcept
+{
+ while (m_retry && m_error_repeat <= DBI_MAX_CONN_ATTEMPTS)
+ {
+ m_conn_ok = false;
+ if (dbi_conn_connect(m_conn) == 0)
+ {
+ init_error();
+ m_conn_ok = true;
+ return true;
+ }
+#ifdef G_OS_WIN32
+ const guint backoff_msecs = 1;
+ Sleep (backoff_msecs * 2 << ++m_error_repeat);
+#else
+ const guint backoff_usecs = 1000;
+ usleep (backoff_usecs * 2 << ++m_error_repeat);
+#endif
+ PINFO ("DBI error: %s - Reconnecting...\n", msg);
+
+ }
+ PERR ("DBI error: %s - Giving up after %d consecutive attempts.\n", msg,
+ DBI_MAX_CONN_ATTEMPTS);
+ m_conn_ok = false;
+ return false;
+}
+
+
+dbi_result
+GncDbiSqlConnection::table_manage_backup (const std::string& table_name,
+ TableOpType op)
+{
+ auto new_name = table_name + "_back";
+ dbi_result result = nullptr;
+ switch (op)
+ {
+ case backup:
+ result = dbi_conn_queryf (m_conn, "ALTER TABLE %s RENAME TO %s",
+ table_name.c_str(), new_name.c_str());
+ break;
+ case rollback:
+ result = dbi_conn_queryf (m_conn,
+ "ALTER TABLE %s RENAME TO %s",
+ new_name.c_str(), table_name.c_str());
+ break;
+ case drop_backup:
+ result = dbi_conn_queryf (m_conn, "DROP TABLE %s",
+ new_name.c_str());
+ break;
+ default:
+ break;
+ }
+ return result;
+}
diff --git a/src/backend/dbi/test/CMakeLists.txt b/src/backend/dbi/test/CMakeLists.txt
index 11a6bfe..cc09d9d 100644
--- a/src/backend/dbi/test/CMakeLists.txt
+++ b/src/backend/dbi/test/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(test_dbi_backend_SOURCES
test-dbi-business-stuff.cpp
test-dbi-stuff.cpp
../gnc-backend-dbi.cpp
+ ../gnc-dbisqlconnection.cpp
)
# This test does not work on Win32
diff --git a/src/backend/dbi/test/Makefile.am b/src/backend/dbi/test/Makefile.am
index ae2f057..cd6a5f4 100644
--- a/src/backend/dbi/test/Makefile.am
+++ b/src/backend/dbi/test/Makefile.am
@@ -61,6 +61,7 @@ test_backend_dbi_SOURCES = \
test-backend-dbi-basic.cpp \
test-dbi-stuff.cpp \
test-dbi-business-stuff.cpp \
+ ../gnc-dbisqlconnection.cpp \
../gnc-backend-dbi.cpp
test_backend_dbi_CPPFLAGS = \
commit ccbfb69cf1419e100c7b83c1f54b4b2c73024804
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jul 18 10:31:20 2016 -0700
Delete unused or duplicated member variables from GncSqlBackend & GncDbiBackend.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index ebb0fc5..8f559d9 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -1480,8 +1480,7 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
if (loadType == LOAD_TYPE_INITIAL_LOAD)
{
- g_assert (be->primary_book == nullptr);
- be->primary_book = book;
+ g_assert (be->sql_be.book == nullptr);
// Set up table version information
gnc_sql_init_version_info (&be->sql_be);
@@ -1677,7 +1676,7 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
g_return_if_fail (be != nullptr);
g_return_if_fail (book != nullptr);
- ENTER ("book=%p, primary=%p", book, be->primary_book);
+ ENTER ("book=%p, primary=%p", book, be->sql_be.book);
dbname = dbi_conn_get_option (be->conn, "dbname");
auto table_list = conn->m_provider->get_table_list (conn->m_conn, dbname);
if (!conn_table_operation (conn, table_list, backup))
@@ -1700,8 +1699,6 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
return;
}
}
- be->is_pristine_db = TRUE;
- be->primary_book = book;
gnc_sql_sync_all (&be->sql_be, book);
if (qof_backend_check_error (qbe))
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index cba8732..d07fe26 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -82,16 +82,7 @@ struct GncDbiBackend
dbi_conn conn;
- QofBook* primary_book; /* The primary, main open book */
- gboolean loading; /* We are performing an initial load */
- gboolean in_query;
- gboolean supports_transactions;
- gboolean is_pristine_db; // Are we saving to a new pristine db?
gboolean exists; // Does the database exist?
-
- gint obj_total; // Total # of objects (for percentage calculation)
- gint operations_done; // Number of operations (save/load) done
-// GHashTable* versions; // Version number for each table
};
class GncDbiSqlConnection : public GncSqlConnection
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index be0338d..f51a3a8 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -450,12 +450,6 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
/* Save all contents */
be->book = book;
- be->obj_total = 0;
- be->obj_total += 1 + gnc_account_n_descendants (gnc_book_get_root_account (
- book));
- be->obj_total += gnc_book_count_transactions (book);
- be->operations_done = 0;
-
is_ok = be->conn->begin_transaction ();
// FIXME: should write the set of commodities that are used
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 334199d..0a79551 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -73,8 +73,6 @@ struct GncSqlBackend
gboolean loading; /**< We are performing an initial load */
gboolean in_query; /**< We are processing a query */
gboolean is_pristine_db; /**< Are we saving to a new pristine db? */
- gint obj_total; /**< Total # of objects (for percentage calculation) */
- gint operations_done; /**< Number of operations (save/load) done */
GHashTable* versions; /**< Version number for each table */
const gchar* timespec_format; /**< Format string for SQL for timespec values */
};
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index f418c19..509af0e 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -637,7 +637,7 @@ test_gnc_sql_convert_timespec_to_string ()
nullptr, nullptr, nullptr, nullptr, ERR_BACKEND_NO_ERR, nullptr,
0, nullptr
},
- nullptr, nullptr, FALSE, FALSE, FALSE, 0, 0, nullptr,
+ nullptr, nullptr, FALSE, FALSE, FALSE, nullptr,
"%4d-%02d-%02d %02d:%02d:%02d"
};
const char* date[numtests] = {"1995-03-11 19:17:26",
commit c0a193c593d5e28d403373186e06a773ee397441
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jul 18 09:49:41 2016 -0700
Remove unused/never implemented QofBackend functions.
Note that the QofQuery functions that sort-of used them are ifdefed out
instead of deleted to serve as place-holders since we'll be bringing
back backend querying later.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index e396559..ebb0fc5 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -1766,22 +1766,11 @@ init_sql_backend (GncDbiBackend* dbi_be)
be->commit = gnc_dbi_commit_edit;
be->rollback = gnc_dbi_rollback_edit;
- /* The gda backend will not be multi-user (for now)... */
- be->events_pending = nullptr;
- be->process_events = nullptr;
-
/* The SQL/DBI backend doesn't need to be synced until it is
* configured for multiuser access. */
be->sync = gnc_dbi_safe_sync_all;
be->safe_sync = gnc_dbi_safe_sync_all;
-
-// be->compile_query = gnc_sql_compile_query;
-// be->run_query = gnc_sql_run_query;
-// be->free_query = gnc_sql_free_query;
- be->compile_query = nullptr;
- be->run_query = nullptr;
- be->free_query = nullptr;
-
+ /* CoA Export function not implemented for the SQL backend. */
be->export_fn = nullptr;
gnc_sql_init (&dbi_be->sql_be);
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index 3dc7ea4..f418c19 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -634,8 +634,8 @@ test_gnc_sql_convert_timespec_to_string ()
{
GncSqlBackend be = {{
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, ERR_BACKEND_NO_ERR, nullptr, 0, nullptr, nullptr
+ nullptr, nullptr, nullptr, nullptr, ERR_BACKEND_NO_ERR, nullptr,
+ 0, nullptr
},
nullptr, nullptr, FALSE, FALSE, FALSE, 0, 0, nullptr,
"%4d-%02d-%02d %02d:%02d:%02d"
diff --git a/src/backend/xml/gnc-backend-xml.cpp b/src/backend/xml/gnc-backend-xml.cpp
index 3fc61e1..40ab3cf 100644
--- a/src/backend/xml/gnc-backend-xml.cpp
+++ b/src/backend/xml/gnc-backend-xml.cpp
@@ -1243,15 +1243,6 @@ QofXmlBackendProvider::create_backend(void)
be->commit = NULL;
be->rollback = xml_rollback_edit;
- /* The file backend always loads all data ... */
- be->compile_query = NULL;
- be->free_query = NULL;
- be->run_query = NULL;
-
- /* The file backend will never be multi-user... */
- be->events_pending = NULL;
- be->process_events = NULL;
-
be->sync = xml_sync_all;
be->export_fn = gnc_xml_be_write_accounts_to_file;
diff --git a/src/libqof/qof/qofbackend-p.h b/src/libqof/qof/qofbackend-p.h
index d8f0a68..9eb0e65 100644
--- a/src/libqof/qof/qofbackend-p.h
+++ b/src/libqof/qof/qofbackend-p.h
@@ -259,16 +259,12 @@ struct QofBackend_s
void (*commit) (QofBackend *, QofInstance *);
void (*rollback) (QofBackend *, QofInstance *);
- gpointer (*compile_query) (QofBackend *, QofQuery *);
- void (*free_query) (QofBackend *, gpointer);
- void (*run_query) (QofBackend *, gpointer);
-
void (*sync) (QofBackend *, /*@ dependent @*/ QofBook *);
void (*safe_sync) (QofBackend *, /*@ dependent @*/ QofBook *);
-
- gboolean (*events_pending) (QofBackend *);
- gboolean (*process_events) (QofBackend *);
-
+ /* This is implented only in the XML backend where it exports only a chart
+ * of accounts.
+ */
+ void (*export_fn) (QofBackend *, QofBook *);
QofBePercentageFunc percentage;
QofBackendError last_err;
@@ -279,24 +275,6 @@ struct QofBackend_s
* This holds the filepath and communicates it to the frontends.
*/
char * fullpath;
-
- /** \deprecated price_lookup should be removed during the redesign
- * of the SQL backend... prices can now be queried using
- * the generic query mechanism.
- *
- * Note the correct signature for this call is
- * void (*price_lookup) (QofBackend *, GNCPriceLookup *);
- * we use gpointer to avoid an unwanted include file dependency.
- */
- void (*price_lookup) (QofBackend *, gpointer);
-
- /** \deprecated Export should really _NOT_ be here, but is left here for now.
- * I'm not sure where this should be going to. It should be
- * removed ASAP. This is a temporary hack-around until period-closing
- * is fully implemented.
- */
- void (*export_fn) (QofBackend *, QofBook *);
-
};
#ifdef __cplusplus
diff --git a/src/libqof/qof/qofbackend.cpp b/src/libqof/qof/qofbackend.cpp
index 4076df5..6613fed 100644
--- a/src/libqof/qof/qofbackend.cpp
+++ b/src/libqof/qof/qofbackend.cpp
@@ -150,24 +150,15 @@ qof_backend_init(QofBackend *be)
be->commit = NULL;
be->rollback = NULL;
- be->compile_query = NULL;
- be->free_query = NULL;
- be->run_query = NULL;
-
be->sync = NULL;
be->safe_sync = NULL;
- be->events_pending = NULL;
- be->process_events = NULL;
+ be->export_fn = NULL;
be->last_err = ERR_BACKEND_NO_ERR;
if (be->error_msg) g_free (be->error_msg);
be->error_msg = NULL;
be->percentage = NULL;
-
- /* to be removed */
- be->price_lookup = NULL;
- be->export_fn = NULL;
}
void
diff --git a/src/libqof/qof/qofquery.cpp b/src/libqof/qof/qofquery.cpp
index 1129971..c6cad34 100644
--- a/src/libqof/qof/qofquery.cpp
+++ b/src/libqof/qof/qofquery.cpp
@@ -548,7 +548,7 @@ static void compile_terms (QofQuery *q)
compile_sort (&(q->tertiary_sort), q->search_for);
q->defaultSort = qof_class_get_default_sort (q->search_for);
-
+#ifdef QOF_BACKEND_QUERY
/* Now compile the backend instances */
for (node = q->books; node; node = node->next)
{
@@ -561,7 +561,9 @@ static void compile_terms (QofQuery *q)
if (result)
g_hash_table_insert (q->be_compiled, book, result);
}
+
}
+#endif
LEAVE (" query=%p", q);
}
@@ -621,12 +623,13 @@ static GList * merge_books (GList *l1, GList *l2)
static gboolean
query_free_compiled (gpointer key, gpointer value, gpointer not_used)
{
+#ifdef QOF_BACKEND_QUERY
QofBook* book = static_cast<QofBook*>(key);
QofBackend* be = book->backend;
if (be && be->free_query)
(be->free_query)(be, value);
-
+#endif
return TRUE;
}
@@ -822,9 +825,10 @@ static void qof_query_run_cb(QofQueryCB* qcb, gpointer cb_arg)
for (node = qcb->query->books; node; node = node->next)
{
QofBook* book = static_cast<QofBook*>(node->data);
+#ifdef QOF_BACKEND_QUERY
QofBackend* be = book->backend;
- /* run the query in the backend */
+
if (be)
{
gpointer compiled_query = g_hash_table_lookup (qcb->query->be_compiled,
@@ -835,7 +839,7 @@ static void qof_query_run_cb(QofQueryCB* qcb, gpointer cb_arg)
(be->run_query) (be, compiled_query);
}
}
-
+#endif
/* And then iterate over all the objects */
qof_object_foreach (qcb->query->search_for, book,
(QofInstanceForeachCB) check_item_cb, qcb);
diff --git a/src/libqof/qof/qofsession.cpp b/src/libqof/qof/qofsession.cpp
index d6f7d6e..cf9c31f 100644
--- a/src/libqof/qof/qofsession.cpp
+++ b/src/libqof/qof/qofsession.cpp
@@ -538,19 +538,13 @@ QofSessionImpl::swap_books (QofSessionImpl & other) noexcept
bool
QofSessionImpl::events_pending () const noexcept
{
- auto backend = qof_book_get_backend (m_book);
- if (!backend) return false;
- if (!backend->events_pending) return false;
- return backend->events_pending (backend);
+ return false;
}
bool
QofSessionImpl::process_events () const noexcept
{
- auto backend = qof_book_get_backend (m_book);
- if (!backend) return false;
- if (!backend->process_events) return false;
- return backend->process_events (backend);
+ return false;
}
/* XXX This exports the list of accounts to a file. It does not
diff --git a/src/libqof/qof/test/test-qofsession-old.cpp b/src/libqof/qof/test/test-qofsession-old.cpp
index f61baaa..0369c7a 100644
--- a/src/libqof/qof/test/test-qofsession-old.cpp
+++ b/src/libqof/qof/test/test-qofsession-old.cpp
@@ -681,44 +681,6 @@ mock_events_fn (QofBackend *be)
return TRUE;
}
-static void
-test_qof_session_events (Fixture *fixture, gconstpointer pData)
-{
- QofBackend *be = NULL;
-
- g_test_message ("Test pending events null checks");
- g_assert (!qof_session_events_pending (NULL));
- g_assert (!qof_book_get_backend (qof_session_get_book (fixture->session)));
- g_assert (!qof_session_events_pending (fixture->session));
- be = g_new0 (QofBackend, 1);
- g_assert (be);
- be->events_pending = NULL;
- qof_book_set_backend (qof_session_get_book (fixture->session), be);
- g_assert (!qof_session_events_pending (fixture->session));
-
- g_test_message ("Test pending events callback");
- be->events_pending = mock_events_fn;
- events_struct.called = FALSE;
- events_struct.be = be;
- g_assert (qof_session_events_pending (fixture->session));
- g_assert (events_struct.called);
-
- g_test_message ("Test process events null checks");
- g_assert (!qof_session_process_events (NULL));
- qof_book_set_backend (qof_session_get_book (fixture->session), NULL);
- g_assert (!qof_session_process_events (fixture->session));
- be->process_events = NULL;
- qof_book_set_backend (qof_session_get_book (fixture->session), be);
- g_assert (!qof_session_process_events (fixture->session));
-
- g_test_message ("Test process events callback");
- be->process_events = mock_events_fn;
- events_struct.called = FALSE;
- events_struct.be = be;
- g_assert (qof_session_process_events (fixture->session));
- g_assert (events_struct.called);
-}
-
static struct
{
QofBackend *be;
@@ -854,7 +816,6 @@ test_suite_qofsession ( void )
GNC_TEST_ADD (suitename, "qof session end", Fixture, NULL, setup, test_qof_session_end, teardown);
GNC_TEST_ADD (suitename, "qof session export", Fixture, NULL, setup, test_qof_session_export, teardown);
GNC_TEST_ADD (suitename, "qof session swap data", Fixture, NULL, setup, test_qof_session_swap_data, teardown);
- GNC_TEST_ADD (suitename, "qof session events", Fixture, NULL, setup, test_qof_session_events, teardown);
GNC_TEST_ADD (suitename, "qof session data loaded", Fixture, NULL, setup, test_qof_session_data_loaded, teardown);
GNC_TEST_ADD (suitename, "qof session get book", Fixture, NULL, setup, test_qof_session_get_book, teardown);
GNC_TEST_ADD (suitename, "qof session get error", Fixture, NULL, setup, test_qof_session_get_error, teardown);
diff --git a/src/libqof/qof/test/test-qofsession.cpp b/src/libqof/qof/test/test-qofsession.cpp
index 0b5cd22..7a30cde 100644
--- a/src/libqof/qof/test/test-qofsession.cpp
+++ b/src/libqof/qof/test/test-qofsession.cpp
@@ -77,14 +77,8 @@ QofBackend * test_backend_factory ()
ret->begin = nullptr;
ret->commit = nullptr;
ret->rollback = nullptr;
- ret->compile_query = nullptr;
- ret->free_query = nullptr;
- ret->run_query = nullptr;
- ret->events_pending = nullptr;
- ret->process_events = nullptr;
ret->percentage = nullptr;
ret->config_count = 0;
- ret->price_lookup = nullptr;
return ret;
}
commit eed4a012c3d73b8d1364282dde5531702e887258
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jul 16 17:22:29 2016 -0700
Remove no-longer-needed gnc_table_slist_free.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 6f25037..e396559 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -171,19 +171,6 @@ public:
/* ================================================================= */
-/* Free the contents of a GSList, then free the list. Don't use this
- * if the elements of the list weren't created with g_new! */
-static void
-gnc_table_slist_free (GSList* table_list)
-{
- GSList* list;
- for (list = table_list; list != nullptr; list = g_slist_next (list))
- {
- g_free (list->data);
- }
- g_slist_free (table_list);
-}
-
/* Check if the dbi connection is valid. If not attempt to re-establish it
* Returns TRUE is there is a valid connection in the end or FALSE otherwise
*/
commit 1f52839271e5ebb981a793706bc5db3be6fdec42
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jul 16 17:21:25 2016 -0700
Templatize QofDbiBackendProvider.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 95ba203..6f25037 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -95,46 +95,6 @@ extern "C"
#endif
#endif
-struct QofSQLITEBackendProvider : public QofBackendProvider
-{
- QofSQLITEBackendProvider (const char* name, const char* type) :
- QofBackendProvider {name, type} {}
- QofSQLITEBackendProvider(QofSQLITEBackendProvider&) = delete;
- QofSQLITEBackendProvider operator=(QofSQLITEBackendProvider&) = delete;
- QofSQLITEBackendProvider(QofSQLITEBackendProvider&&) = delete;
- QofSQLITEBackendProvider operator=(QofSQLITEBackendProvider&&) = delete;
- ~QofSQLITEBackendProvider () = default;
- QofBackend* create_backend(void);
- bool type_check(const char* type);
-};
-
-struct QofMYSQLBackendProvider : public QofBackendProvider
-{
- QofMYSQLBackendProvider (const char* name, const char* type) :
- QofBackendProvider {name, type} {}
- QofMYSQLBackendProvider(QofMYSQLBackendProvider&) = delete;
- QofMYSQLBackendProvider operator=(QofMYSQLBackendProvider&) = delete;
- QofMYSQLBackendProvider(QofMYSQLBackendProvider&&) = delete;
- QofMYSQLBackendProvider operator=(QofMYSQLBackendProvider&&) = delete;
- ~QofMYSQLBackendProvider () = default;
- QofBackend* create_backend(void);
- bool type_check(const char* type) { return true; }
-};
-
-struct QofPGSQLBackendProvider : public QofBackendProvider
-{
- QofPGSQLBackendProvider (const char* name, const char* type) :
- QofBackendProvider {name, type} {}
- QofPGSQLBackendProvider(QofPGSQLBackendProvider&) = delete;
- QofPGSQLBackendProvider operator=(QofPGSQLBackendProvider&) = delete;
- QofPGSQLBackendProvider(QofPGSQLBackendProvider&&) = delete;
- QofPGSQLBackendProvider operator=(QofPGSQLBackendProvider&&) = delete;
- ~QofPGSQLBackendProvider () = default;
- QofBackend* create_backend(void);
- bool type_check(const char* type) { return true; }
-
-};
-
#if LIBDBI_VERSION >= 900
#define HAVE_LIBDBI_R 1
#define HAVE_LIBDBI_TO_LONGLONG 1
@@ -194,6 +154,20 @@ public:
void drop_index(dbi_conn conn, const std::string& index);
};
+template <DbType T>
+class QofDbiBackendProvider : public QofBackendProvider
+{
+public:
+ QofDbiBackendProvider (const char* name, const char* type) :
+ QofBackendProvider {name, type} {}
+ QofDbiBackendProvider(QofDbiBackendProvider&) = delete;
+ QofDbiBackendProvider operator=(QofDbiBackendProvider&) = delete;
+ QofDbiBackendProvider(QofDbiBackendProvider&&) = delete;
+ QofDbiBackendProvider operator=(QofDbiBackendProvider&&) = delete;
+ ~QofDbiBackendProvider () = default;
+ QofBackend* create_backend(void);
+ bool type_check(const char* type) { return true; }
+};
/* ================================================================= */
@@ -1850,20 +1824,20 @@ new_backend (void (*session_begin) (QofBackend*, QofSession*, const gchar*,
return be;
}
-QofBackend*
-QofSQLITEBackendProvider::create_backend()
+template<> QofBackend*
+QofDbiBackendProvider<DbType::DBI_SQLITE>::create_backend()
{
return new_backend (gnc_dbi_sqlite3_session_begin);
}
-QofBackend*
-QofMYSQLBackendProvider::create_backend()
+template<> QofBackend*
+QofDbiBackendProvider<DbType::DBI_MYSQL>::create_backend()
{
return new_backend (gnc_dbi_mysql_session_begin);
}
-QofBackend*
-QofPGSQLBackendProvider::create_backend()
+template<> QofBackend*
+QofDbiBackendProvider<DbType::DBI_PGSQL>::create_backend()
{
return new_backend (gnc_dbi_postgres_session_begin);
}
@@ -1871,10 +1845,10 @@ QofPGSQLBackendProvider::create_backend()
/*
* Checks to see whether the file is an sqlite file or not
- *
+ *1980
*/
-bool
-QofSQLITEBackendProvider::type_check(const char *uri)
+template<> bool
+QofDbiBackendProvider<DbType::DBI_SQLITE>::type_check(const char *uri)
{
FILE* f;
gchar buf[50];
@@ -1993,23 +1967,23 @@ gnc_module_init_backend_dbi (void)
if (have_sqlite3_driver)
{
const char* name = "GnuCash Libdbi (SQLITE3) Backend";
- auto prov = QofBackendProvider_ptr(new QofSQLITEBackendProvider{name, FILE_URI_TYPE});
+ auto prov = QofBackendProvider_ptr(new QofDbiBackendProvider<DbType::DBI_SQLITE>{name, FILE_URI_TYPE});
qof_backend_register_provider(std::move(prov));
- prov = QofBackendProvider_ptr(new QofSQLITEBackendProvider{name, SQLITE3_URI_TYPE});
+ prov = QofBackendProvider_ptr(new QofDbiBackendProvider<DbType::DBI_SQLITE>{name, SQLITE3_URI_TYPE});
qof_backend_register_provider(std::move(prov));
}
if (have_mysql_driver)
{
const char *name = "GnuCash Libdbi (MYSQL) Backend";
- auto prov = QofBackendProvider_ptr(new QofMYSQLBackendProvider{name, "mysql"});
+ auto prov = QofBackendProvider_ptr(new QofDbiBackendProvider<DbType::DBI_MYSQL>{name, "mysql"});
qof_backend_register_provider(std::move(prov));
}
if (have_pgsql_driver)
{
const char* name = "GnuCash Libdbi (POSTGRESQL) Backend";
- auto prov = QofBackendProvider_ptr(new QofPGSQLBackendProvider{name, "postgres"});
+ auto prov = QofBackendProvider_ptr(new QofDbiBackendProvider<DbType::DBI_PGSQL>{name, "postgres"});
qof_backend_register_provider(std::move(prov));
}
commit 3894a2e8b76d766b881111688454b2ed262ab5e9
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jul 16 16:39:09 2016 -0700
Convert struct provider_functions_t into virtual class GncDbiProvider.
Implementation templated as template <DbType> GncDbiProviderImpl.
Converted GSLists to std::vectors and GStrings to std::strings.
diff --git a/src/backend/dbi/CMakeLists.txt b/src/backend/dbi/CMakeLists.txt
index 2a3d4a0..711a65d 100644
--- a/src/backend/dbi/CMakeLists.txt
+++ b/src/backend/dbi/CMakeLists.txt
@@ -8,7 +8,7 @@ SET (backend_dbi_SOURCES
gnc-backend-dbi.cpp
)
SET (backend_dbi_noinst_HEADERS
- gnc-backend-dbi.h gnc-backend-dbi-priv.h
+ gnc-backend-dbi.h gnc-backend-dbi.hpp
)
# Add dependency on config.h
diff --git a/src/backend/dbi/Makefile.am b/src/backend/dbi/Makefile.am
index aab8c0f..ac07b8d 100644
--- a/src/backend/dbi/Makefile.am
+++ b/src/backend/dbi/Makefile.am
@@ -25,7 +25,7 @@ libgncmod_backend_dbi_la_SOURCES = \
noinst_HEADERS = \
gnc-backend-dbi.h \
- gnc-backend-dbi-priv.h
+ gnc-backend-dbi.hpp
libgncmod_backend_dbi_la_LDFLAGS = -shared -avoid-version
libgncmod_backend_dbi_la_LIBADD = \
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index cabd8a4..95ba203 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -86,7 +86,7 @@ extern "C"
#include <gnc-datetime.hpp>
#include <gnc-backend-prov.hpp>
#include "gnc-backend-dbi.h"
-#include "gnc-backend-dbi-priv.h"
+#include "gnc-backend-dbi.hpp"
#if PLATFORM(WINDOWS)
#ifdef __STRICT_ANSI_UNSET__
@@ -157,73 +157,43 @@ static gchar lock_table[] = "gnclock";
#define SQLITE3_URI_PREFIX (SQLITE3_URI_TYPE "://")
#define PGSQL_DEFAULT_PORT 5432
-static gchar* conn_create_table_ddl_sqlite3 (const GncSqlConnection* conn,
- const gchar* table_name,
- const ColVec& info_vec);
-static GSList* conn_get_table_list (dbi_conn conn, const gchar* dbname);
-static GSList* conn_get_table_list_sqlite3 (dbi_conn conn, const gchar* dbname);
-static void append_sqlite3_col_def (GString* ddl, const GncSqlColumnInfo& info);
-static GSList *conn_get_index_list_sqlite3 (dbi_conn conn);
-static void conn_drop_index_sqlite3 (dbi_conn conn, const gchar *index);
-static provider_functions_t provider_sqlite3 =
-{
- conn_create_table_ddl_sqlite3,
- conn_get_table_list_sqlite3,
- append_sqlite3_col_def,
- conn_get_index_list_sqlite3,
- conn_drop_index_sqlite3
-};
#define SQLITE3_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
-
-static gchar* conn_create_table_ddl_mysql (const GncSqlConnection* conn,
- const gchar* table_name,
- const ColVec& info_vec);
-static void append_mysql_col_def (GString* ddl, const GncSqlColumnInfo& info);
-static GSList *conn_get_index_list_mysql (dbi_conn conn);
-static void conn_drop_index_mysql (dbi_conn conn, const gchar *index);
-static provider_functions_t provider_mysql =
-{
- conn_create_table_ddl_mysql,
- conn_get_table_list,
- append_mysql_col_def,
- conn_get_index_list_mysql,
- conn_drop_index_mysql
-};
#define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
-
-static gchar* conn_create_table_ddl_pgsql (const GncSqlConnection* conn,
- const gchar* table_name,
- const ColVec& info_vec );
-static GSList* conn_get_table_list_pgsql (dbi_conn conn, const gchar* dbname);
-static void append_pgsql_col_def (GString* ddl, const GncSqlColumnInfo& info);
-static GSList *conn_get_index_list_pgsql (dbi_conn conn);
-static void conn_drop_index_pgsql (dbi_conn conn, const gchar *index);
-
-static provider_functions_t provider_pgsql =
-{
- conn_create_table_ddl_pgsql,
- conn_get_table_list_pgsql,
- append_pgsql_col_def,
- conn_get_index_list_pgsql,
- conn_drop_index_pgsql
-};
#define PGSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d %02d%02d%02d"
static gboolean gnc_dbi_lock_database (QofBackend *qbe, gboolean ignore_lock);
static void gnc_dbi_unlock (QofBackend *qbe);
static gboolean save_may_clobber_data (QofBackend* qbe);
-static gchar* create_index_ddl (const GncSqlConnection* conn,
- const gchar* index_name,
- const gchar* table_name,
- const EntryVec& col_table);
+static std::string create_index_ddl (const GncSqlConnection* conn,
+ const std::string& index_name,
+ const std::string& table_name,
+ const EntryVec& col_table);
static GncDbiTestResult conn_test_dbi_library (dbi_conn conn);
-#define GNC_DBI_PROVIDER_SQLITE (&provider_sqlite3)
-#define GNC_DBI_PROVIDER_MYSQL (&provider_mysql)
-#define GNC_DBI_PROVIDER_PGSQL (&provider_pgsql)
-
#define DBI_MAX_CONN_ATTEMPTS 5
+enum class DbType
+{
+ DBI_SQLITE,
+ DBI_MYSQL,
+ DBI_PGSQL
+};
+
+
+template <DbType T>
+class GncDbiProviderImpl : public GncDbiProvider
+{
+public:
+ std::string create_table_ddl(const GncSqlConnection* conn,
+ const std::string& table_name,
+ const ColVec& info_vec);
+ std::vector<std::string> get_table_list(dbi_conn conn,
+ const std::string& dbname);
+ void append_col_def(std::string& ddl, const GncSqlColumnInfo& info);
+ std::vector<std::string> get_index_list (dbi_conn conn);
+ void drop_index(dbi_conn conn, const std::string& index);
+};
+
/* ================================================================= */
@@ -454,8 +424,8 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
{
delete (be->sql_be.conn);
}
- be->sql_be.conn = new GncDbiSqlConnection (GNC_DBI_PROVIDER_SQLITE, qbe,
- be->conn);
+ be->sql_be.conn = new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_SQLITE>,
+ qbe, be->conn);
be->sql_be.timespec_format = SQLITE3_TIMESPEC_STR_FORMAT;
/* We should now have a proper session set up.
@@ -470,33 +440,31 @@ exit:
LEAVE ("%s", msg);
}
-static GSList*
-conn_get_index_list_sqlite3 (dbi_conn conn)
+template<> std::vector<std::string>
+GncDbiProviderImpl<DbType::DBI_SQLITE>::get_index_list (dbi_conn conn)
{
- GSList* list = nullptr;
- const gchar* errmsg;
+ std::vector<std::string> retval;
+ const char* errmsg;
dbi_result result = dbi_conn_query (conn,
"SELECT name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_autoindex%'");
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
- g_print ("Index Table Retrieval Error: %s\n", errmsg);
- return nullptr;
+ PWARN ("Index Table Retrieval Error: %s\n", errmsg);
+ return retval;
}
while (dbi_result_next_row (result) != 0)
{
- const gchar* index_name;
-
- index_name = dbi_result_get_string_idx (result, 1);
- list = g_slist_prepend (list, strdup (index_name));
+ std::string index_name {dbi_result_get_string_idx (result, 1)};
+ retval.push_back(index_name);
}
dbi_result_free (result);
- return list;
+ return retval;
}
-static void
-conn_drop_index_sqlite3 (dbi_conn conn, const gchar* index)
+template <DbType P> void
+GncDbiProviderImpl<P>::drop_index(dbi_conn conn, const std::string& index)
{
- dbi_result result = dbi_conn_queryf (conn, "DROP INDEX %s", index);
+ dbi_result result = dbi_conn_queryf (conn, "DROP INDEX %s", index.c_str());
if (result)
dbi_result_free (result);
}
@@ -1111,8 +1079,8 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
{
delete (be->sql_be.conn);
}
- be->sql_be.conn = new GncDbiSqlConnection (GNC_DBI_PROVIDER_MYSQL, qbe,
- be->conn);
+ be->sql_be.conn = new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
+ qbe, be->conn);
}
be->sql_be.timespec_format = MYSQL_TIMESPEC_STR_FORMAT;
@@ -1135,69 +1103,60 @@ exit:
LEAVE (" ");
}
-static GSList*
-conn_get_index_list_mysql (dbi_conn conn)
+template<> std::vector<std::string>
+GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
{
- GSList* index_list = nullptr;
- dbi_result table_list;
+ std::vector<std::string> retval;
const char* errmsg;
- const gchar* dbname = dbi_conn_get_option (conn, "dbname");
- g_return_val_if_fail (conn != nullptr, nullptr);
- table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
+ auto dbname = dbi_conn_get_option (conn, "dbname");
+ auto table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
- g_print ("Table Retrieval Error: %s\n", errmsg);
- return nullptr;
+ PWARN ("Table Retrieval Error: %s\n", errmsg);
+ return retval;
}
while (dbi_result_next_row (table_list) != 0)
{
- dbi_result result;
- const gchar* table_name = dbi_result_get_string_idx (table_list, 1);
- result = dbi_conn_queryf (conn,
- "SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
- table_name);
+ auto table_name = dbi_result_get_string_idx (table_list, 1);
+ auto result = dbi_conn_queryf (conn,
+ "SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
+ table_name);
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
- g_print ("Index Table Retrieval Error: %s\n", errmsg);
+ PWARN ("Index Table Retrieval Error: %s on table %s\n",
+ errmsg, table_name);
continue;
}
while (dbi_result_next_row (result) != 0)
{
- const gchar* index_name = dbi_result_get_string_idx (result, 3);
- index_list = g_slist_prepend (index_list, g_strjoin (" ", index_name,
- table_name, nullptr));
+ std::string index_name {dbi_result_get_string_idx (result, 3)};
+ retval.push_back(index_name + " " + table_name);
}
dbi_result_free (result);
}
- return index_list;
+ return retval;
}
-static void
-conn_drop_index_mysql (dbi_conn conn, const gchar* index)
+template<> void
+GncDbiProviderImpl<DbType::DBI_MYSQL>::drop_index (dbi_conn conn, const std::string& index)
{
- dbi_result result;
- gchar** index_table_split = g_strsplit (index, " ", 2);
- int splitlen = -1;
-
- /* Check if the index split can be valid */
- while (index_table_split[++splitlen] != nullptr)
- { /* do nothing, just count split members */ }
-
- if (splitlen != 2)
+ unsigned int sep{0}, count{0};
+ while ((sep = index.find(' ', sep)) != std::string::npos)
+ ++count;
+ if (count != 1)
{
- g_print ("Drop index error: invalid MySQL index format (<index> <table>): %s",
- index);
+ PWARN("Drop index error: invalid MySQL index format (<index> <table>): %s",
+ index.c_str());
return;
}
- result = dbi_conn_queryf (conn, "DROP INDEX %s ON %s",
- index_table_split[0], index_table_split[1]);
+ auto result = dbi_conn_queryf (conn, "DROP INDEX %s ON %s",
+ index.substr(0, sep).c_str(),
+ index.substr(sep + 1).c_str());
if (result)
dbi_result_free (result);
-
- g_strfreev (index_table_split);
}
static void
@@ -1450,8 +1409,8 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
{
delete (be->sql_be.conn);
}
- be->sql_be.conn = new GncDbiSqlConnection (GNC_DBI_PROVIDER_PGSQL, qbe,
- be->conn);
+ be->sql_be.conn = new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_PGSQL>,
+ qbe, be->conn);
}
be->sql_be.timespec_format = PGSQL_TIMESPEC_STR_FORMAT;
@@ -1475,40 +1434,28 @@ exit:
LEAVE (" ");
}
-static GSList*
-conn_get_index_list_pgsql (dbi_conn conn)
+template<> std::vector<std::string>
+GncDbiProviderImpl<DbType::DBI_PGSQL>::get_index_list (dbi_conn conn)
{
- GSList* list = nullptr;
- const gchar* errmsg;
- dbi_result result;
+ std::vector<std::string> retval;
+ const char* errmsg;
PINFO ("Retrieving postgres index list\n");
- result = dbi_conn_query (conn,
- "SELECT relname FROM pg_class AS a INNER JOIN pg_index AS b ON (b.indexrelid = a.oid) INNER JOIN pg_namespace AS c ON (a.relnamespace = c.oid) WHERE reltype = '0' AND indisprimary = 'f' AND nspname = 'public'");
+ auto result = dbi_conn_query (conn,
+ "SELECT relname FROM pg_class AS a INNER JOIN pg_index AS b ON (b.indexrelid = a.oid) INNER JOIN pg_namespace AS c ON (a.relnamespace = c.oid) WHERE reltype = '0' AND indisprimary = 'f' AND nspname = 'public'");
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
- g_print ("Index Table Retrieval Error: %s\n", errmsg);
- return nullptr;
+ PWARN("Index Table Retrieval Error: %s\n", errmsg);
+ return retval;
}
while (dbi_result_next_row (result) != 0)
{
- const gchar* index_name;
-
- index_name = dbi_result_get_string_idx (result, 1);
- list = g_slist_prepend (list, strdup (index_name));
+ std::string index_name {dbi_result_get_string_idx (result, 1)};
+ retval.push_back(index_name);
}
dbi_result_free (result);
- return list;
-}
-
-static void
-conn_drop_index_pgsql (dbi_conn conn, const gchar* index)
-{
- dbi_result result = dbi_conn_queryf (conn, "DROP INDEX %s", index);
- if (result)
- dbi_result_free (result);
+ return retval;
}
-
/* ================================================================= */
static void
@@ -1682,24 +1629,20 @@ GncDbiSqlConnection::table_manage_backup (const std::string& table_name,
*/
gboolean
-conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
+conn_table_operation (GncSqlConnection* sql_conn,
+ std::vector<std::string> table_name_list,
TableOpType op)
{
- GSList* node;
gboolean result = TRUE;
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (sql_conn);
- GSList* full_table_name_list = nullptr;
const gchar* dbname = dbi_conn_get_option (conn->m_conn, "dbname");
- g_return_val_if_fail (table_name_list != nullptr, FALSE);
- if (op == rollback)
- full_table_name_list =
- conn->m_provider->get_table_list (conn->m_conn, dbname);
+ g_return_val_if_fail (!table_name_list.empty(), FALSE);
- for (node = table_name_list; node != nullptr && result; node = node->next)
+ for (auto table : table_name_list)
{
- gchar* table_name = (gchar*)node->data;
dbi_result result;
+ auto table_name = table.c_str();
/* Ignore the lock table */
if (g_strcmp0 (table_name, lock_table) == 0)
{
@@ -1711,14 +1654,20 @@ conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
switch (op)
{
case rollback:
- if (g_slist_find (full_table_name_list, table_name))
+ {
+ auto full_table_name_list =
+ conn->m_provider->get_table_list (conn->m_conn, dbname);
+ if (std::find (full_table_name_list.begin(),
+ full_table_name_list.end(),
+ table_name) != full_table_name_list.end())
{
result = dbi_conn_queryf (conn->m_conn, "DROP TABLE %s",
table_name);
if (result)
break;
}
- /* Fall through */
+ }
+ /* Fall through */
case backup:
case drop_backup:
result = conn->table_manage_backup (table_name, op);
@@ -1744,7 +1693,6 @@ conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
}
}
}
- gnc_table_slist_free (full_table_name_list);
return result;
}
@@ -1763,7 +1711,6 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
GncDbiBackend* be = (GncDbiBackend*)qbe;
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (((GncSqlBackend*)
be)->conn);
- GSList* table_list, *index_list, *iter;
const gchar* dbname = nullptr;
g_return_if_fail (be != nullptr);
@@ -1771,49 +1718,38 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
ENTER ("book=%p, primary=%p", book, be->primary_book);
dbname = dbi_conn_get_option (be->conn, "dbname");
- table_list = conn->m_provider->get_table_list (conn->m_conn, dbname);
- if (!conn_table_operation ((GncSqlConnection*)conn, table_list,
- backup))
+ auto table_list = conn->m_provider->get_table_list (conn->m_conn, dbname);
+ if (!conn_table_operation (conn, table_list, backup))
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- conn_table_operation ((GncSqlConnection*)conn, table_list,
- rollback);
+ conn_table_operation (conn, table_list, rollback);
LEAVE ("Failed to rename tables");
- gnc_table_slist_free (table_list);
return;
}
- index_list = conn->m_provider->get_index_list (conn->m_conn);
- for (iter = index_list; iter != nullptr; iter = g_slist_next (iter))
+ auto index_list = conn->m_provider->get_index_list (conn->m_conn);
+ for (auto index : index_list)
{
const char* errmsg;
- conn->m_provider->drop_index (conn->m_conn, static_cast<char*> (iter->data));
+ conn->m_provider->drop_index (conn->m_conn, index);
if (DBI_ERROR_NONE != dbi_conn_error (conn->m_conn, &errmsg))
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
- gnc_table_slist_free (index_list);
- conn_table_operation ((GncSqlConnection*)conn, table_list,
- rollback);
- gnc_table_slist_free (table_list);
+ conn_table_operation (conn, table_list, rollback);
LEAVE ("Failed to drop indexes %s", errmsg);
return;
}
}
- gnc_table_slist_free (index_list);
-
be->is_pristine_db = TRUE;
be->primary_book = book;
gnc_sql_sync_all (&be->sql_be, book);
if (qof_backend_check_error (qbe))
{
- conn_table_operation ((GncSqlConnection*)conn, table_list,
- rollback);
+ conn_table_operation (conn, table_list, rollback);
LEAVE ("Failed to create new database tables");
return;
}
- conn_table_operation ((GncSqlConnection*)conn, table_list,
- drop_backup);
- gnc_table_slist_free (table_list);
+ conn_table_operation (conn, table_list, drop_backup);
LEAVE ("book=%p", book);
}
/* ================================================================= */
@@ -2451,59 +2387,49 @@ GncDbiSqlConnection::commit_transaction () const noexcept
return success;
}
-static gchar*
-create_index_ddl (const GncSqlConnection* conn, const char* index_name,
- const char* table_name, const EntryVec& col_table)
+static std::string
+create_index_ddl (const GncSqlConnection* conn, const std::string& index_name,
+ const std::string& table_name, const EntryVec& col_table)
{
- GString* ddl;
-
- g_return_val_if_fail (conn != nullptr, nullptr);
- g_return_val_if_fail (index_name != nullptr, nullptr);
- g_return_val_if_fail (table_name != nullptr, nullptr);
-
- ddl = g_string_new ("");
- g_string_printf (ddl, "CREATE INDEX %s ON %s (", index_name, table_name);
+ std::string ddl;
+ ddl += "CREATE INDEX " + index_name + " ON " + table_name + "(";
for (auto const table_row : col_table)
{
if (table_row != *col_table.begin())
{
- (void)g_string_append (ddl, ", ");
+ ddl =+ ", ";
}
- g_string_append_printf (ddl, "%s", table_row->name());
+ ddl += table_row->name();
}
- (void)g_string_append (ddl, ")");
-
- return g_string_free (ddl, FALSE);
+ ddl += ")";
+ return ddl;
}
-gchar*
+std::string
add_columns_ddl(const GncSqlConnection* conn,
- const gchar* table_name,
+ const std::string& table_name,
const ColVec& info_vec)
{
- GString* ddl;
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
+ std::string ddl;
+ const GncDbiSqlConnection* dbi_conn = dynamic_cast<decltype(dbi_conn)>(conn);
g_return_val_if_fail (conn != nullptr, nullptr);
- g_return_val_if_fail (table_name != nullptr, nullptr);
-
- ddl = g_string_new ("");
- g_string_printf (ddl, "ALTER TABLE %s ", table_name);
+ ddl += "ALTER TABLE " + table_name;
for (auto const& info : info_vec)
{
if (info != *info_vec.begin())
{
- (void)g_string_append (ddl, ", ");
+ ddl += ", ";
}
- g_string_append (ddl, "ADD COLUMN ");
+ ddl += "ADD COLUMN ";
dbi_conn->m_provider->append_col_def (ddl, info);
}
-
- return g_string_free (ddl, FALSE);
+ return ddl;
}
-static void
-append_sqlite3_col_def(GString* ddl, const GncSqlColumnInfo& info)
+template<> void
+GncDbiProviderImpl<DbType::DBI_SQLITE>::append_col_def(std::string& ddl,
+ const GncSqlColumnInfo& info)
{
const char* type_name = nullptr;
@@ -2529,53 +2455,51 @@ append_sqlite3_col_def(GString* ddl, const GncSqlColumnInfo& info)
PERR ("Unknown column type: %d\n", info.m_type);
type_name = "";
}
- g_string_append_printf (ddl, "%s %s", info.m_name.c_str(), type_name);
+ ddl += (info.m_name + " " + type_name);
if (info.m_size != 0)
{
- (void)g_string_append_printf (ddl, "(%d)", info.m_size);
+ ddl += "(" + std::to_string(info.m_size) + ")";
}
if (info.m_primary_key)
{
- (void)g_string_append (ddl, " PRIMARY KEY");
+ ddl += " PRIMARY KEY";
}
if (info.m_autoinc)
{
- (void)g_string_append (ddl, " AUTOINCREMENT");
+ ddl += " AUTOINCREMENT";
}
if (info.m_not_null)
{
- (void)g_string_append (ddl, " NOT NULL");
+ ddl += " NOT NULL";
}
}
-static gchar*
-conn_create_table_ddl_sqlite3 (const GncSqlConnection* conn,
- const gchar* table_name,
- const ColVec& info_vec)
+template <DbType P> std::string
+GncDbiProviderImpl<P>::create_table_ddl (const GncSqlConnection* conn,
+ const std::string& table_name,
+ const ColVec& info_vec)
{
- GString* ddl;
+ std::string ddl;
unsigned int col_num = 0;
- g_return_val_if_fail (conn != nullptr, nullptr);
- g_return_val_if_fail (table_name != nullptr, nullptr);
-
- ddl = g_string_new ("");
- g_string_printf (ddl, "CREATE TABLE %s (", table_name);
+ g_return_val_if_fail (conn != nullptr, ddl);
+ ddl += "CREATE TABLE " + table_name + "(";
for (auto const& info : info_vec)
{
if (col_num++ != 0)
{
- (void)g_string_append (ddl, ", ");
+ ddl += ", ";
}
- append_sqlite3_col_def (ddl, info);
+ append_col_def (ddl, info);
}
- (void)g_string_append (ddl, ")");
+ ddl += ")";
- return g_string_free (ddl, FALSE);
+ return ddl;
}
-static void
-append_mysql_col_def (GString* ddl, const GncSqlColumnInfo& info)
+template<> void
+GncDbiProviderImpl<DbType::DBI_MYSQL>::append_col_def (std::string& ddl,
+ const GncSqlColumnInfo& info)
{
const char* type_name = nullptr;
@@ -2608,56 +2532,33 @@ append_mysql_col_def (GString* ddl, const GncSqlColumnInfo& info)
PERR ("Unknown column type: %d\n", info.m_type);
type_name = "";
}
- g_string_append_printf (ddl, "%s %s", info.m_name.c_str(), type_name);
+ ddl += info.m_name + " " + type_name;
if (info.m_size != 0 && info.m_type == BCT_STRING)
{
- g_string_append_printf (ddl, "(%d)", info.m_size);
+ ddl += std::to_string(info.m_size);
}
if (info.m_unicode)
{
- (void)g_string_append (ddl, " CHARACTER SET utf8");
+ ddl += " CHARACTER SET utf8";
}
if (info.m_primary_key)
{
- (void)g_string_append (ddl, " PRIMARY KEY");
+ ddl += " PRIMARY KEY";
}
if (info.m_autoinc)
{
- (void)g_string_append (ddl, " AUTO_INCREMENT");
+ ddl += " AUTO_INCREMENT";
}
if (info.m_not_null)
{
- (void)g_string_append (ddl, " NOT NULL");
+ ddl += " NOT NULL";
}
}
-static gchar*
-conn_create_table_ddl_mysql (const GncSqlConnection* conn,
- const gchar* table_name, const ColVec& info_vec)
-{
- GString* ddl;
- unsigned int col_num = 0;
-
- g_return_val_if_fail (conn != nullptr, nullptr);
- g_return_val_if_fail (table_name != nullptr, nullptr);
-
- ddl = g_string_new ("");
- g_string_printf (ddl, "CREATE TABLE %s (", table_name);
- for (auto const& info : info_vec)
- {
- if (col_num++ != 0)
- {
- (void)g_string_append (ddl, ", ");
- }
- append_mysql_col_def (ddl, info);
- }
- (void)g_string_append (ddl, ")");
- return g_string_free (ddl, FALSE);
-}
-
-static void
-append_pgsql_col_def (GString* ddl, const GncSqlColumnInfo& info)
+template<> void
+GncDbiProviderImpl<DbType::DBI_PGSQL>::append_col_def (std::string& ddl,
+ const GncSqlColumnInfo& info)
{
const char* type_name = nullptr;
@@ -2698,67 +2599,36 @@ append_pgsql_col_def (GString* ddl, const GncSqlColumnInfo& info)
PERR ("Unknown column type: %d\n", info.m_type);
type_name = "";
}
- g_string_append_printf (ddl, "%s %s", info.m_name.c_str(), type_name);
+ ddl += info.m_name + " " + type_name;
if (info.m_size != 0 && info.m_type == BCT_STRING)
{
- g_string_append_printf (ddl, "(%d)", info.m_size);
+ ddl += "(" + std::to_string(info.m_size) + ")";
}
if (info.m_primary_key)
{
- (void)g_string_append (ddl, " PRIMARY KEY");
+ ddl += " PRIMARY KEY";
}
if (info.m_not_null)
{
- (void)g_string_append (ddl, " NOT NULL");
- }
-}
-
-static gchar*
-conn_create_table_ddl_pgsql (const GncSqlConnection* conn, const gchar* table_name,
- const ColVec& info_vec)
-{
- GString* ddl;
- unsigned int col_num = 0;
-
- g_return_val_if_fail (conn != nullptr, nullptr);
- g_return_val_if_fail (table_name != nullptr, nullptr);
-
- ddl = g_string_new ("");
- g_string_printf (ddl, "CREATE TABLE %s (", table_name);
- for (auto const& info : info_vec)
- {
- if (col_num++ != 0)
- {
- (void)g_string_append (ddl, ", ");
- }
- append_pgsql_col_def (ddl, info);
+ ddl += " NOT NULL";
}
- (void)g_string_append (ddl, ")");
-
- return g_string_free (ddl, FALSE);
}
bool
GncDbiSqlConnection::create_table (const std::string& table_name,
const ColVec& info_vec) const noexcept
{
- auto ddl = m_provider->create_table_ddl(this, table_name.c_str(), info_vec);
- if (ddl != nullptr)
- {
+ auto ddl = m_provider->create_table_ddl(this, table_name, info_vec);
+ if (ddl.empty())
+ return false;
- DEBUG ("SQL: %s\n", ddl);
- auto result = dbi_conn_query (m_conn, ddl);
- g_free (ddl);
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
- }
- else
+ DEBUG ("SQL: %s\n", ddl.c_str());
+ auto result = dbi_conn_query (m_conn, ddl.c_str());
+ auto status = dbi_result_free (result);
+ if (status < 0)
{
- return false;
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
return true;
@@ -2769,23 +2639,16 @@ GncDbiSqlConnection::create_index(const std::string& index_name,
const std::string& table_name,
const EntryVec& col_table) const noexcept
{
- auto ddl = create_index_ddl (this, index_name.c_str(), table_name.c_str(),
- col_table);
- if (ddl != nullptr)
- {
- DEBUG ("SQL: %s\n", ddl);
- auto result = dbi_conn_query (m_conn, ddl);
- g_free (ddl);
- auto status = dbi_result_free (result);
- if (status < 0)
- {
- PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
- }
- }
- else
- {
+ auto ddl = create_index_ddl (this, index_name, table_name, col_table);
+ if (ddl.empty())
return false;
+ DEBUG ("SQL: %s\n", ddl.c_str());
+ auto result = dbi_conn_query (m_conn, ddl.c_str());
+ auto status = dbi_result_free (result);
+ if (status < 0)
+ {
+ PERR ("Error in dbi_result_free() result\n");
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
return true;
@@ -2796,13 +2659,12 @@ GncDbiSqlConnection::add_columns_to_table(const std::string& table_name,
const ColVec& info_vec)
const noexcept
{
- auto ddl = add_columns_ddl(this, table_name.c_str(), info_vec);
- if (ddl == nullptr)
- return FALSE;
+ auto ddl = add_columns_ddl(this, table_name, info_vec);
+ if (ddl.empty())
+ return false;
- DEBUG ("SQL: %s\n", ddl);
- auto result = dbi_conn_query (m_conn, ddl);
- g_free (ddl);
+ DEBUG ("SQL: %s\n", ddl.c_str());
+ auto result = dbi_conn_query (m_conn, ddl.c_str());
auto status = dbi_result_free (result);
if (status < 0)
{
@@ -2832,85 +2694,55 @@ GncDbiSqlConnection::quote_string (const std::string& unquoted_str)
}
}
-static GSList*
-conn_get_table_list (dbi_conn conn, const gchar* dbname)
+static std::vector<std::string>
+conn_get_table_list (dbi_conn conn, const std::string& dbname)
{
- GSList* list = nullptr;
-
- auto tables = dbi_conn_get_table_list (conn, dbname, nullptr);
+ std::vector<std::string> retval;
+ auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), nullptr);
while (dbi_result_next_row (tables) != 0)
{
- const gchar* table_name;
-
- table_name = dbi_result_get_string_idx (tables, 1);
- list = g_slist_prepend (list, strdup (table_name));
+ std::string table_name {dbi_result_get_string_idx (tables, 1)};
+ retval.push_back(table_name);
}
dbi_result_free (tables);
- return list;
+ return retval;
}
-static GSList*
-conn_get_table_list_sqlite3 (dbi_conn conn, const gchar* dbname)
+template<> std::vector<std::string>
+GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
+ const std::string& dbname)
{
- gboolean change_made;
-
/* Return the list, but remove the tables that sqlite3 adds for
* its own use. */
- GSList* list = conn_get_table_list (conn, dbname);
- change_made = TRUE;
- while (list != nullptr && change_made)
- {
- GSList* node;
-
- change_made = FALSE;
- for (node = list; node != nullptr; node = node->next)
- {
- const gchar* table_name = (const gchar*)node->data;
-
- if (strcmp (table_name, "sqlite_sequence") == 0)
- {
- g_free (node->data);
- list = g_slist_delete_link (list, node);
- change_made = TRUE;
- break;
- }
- }
- }
+ auto list = conn_get_table_list (conn, dbname);
+ auto end = std::remove(list.begin(), list.end(), "sqlite_sequence");
+ list.erase(end, list.end());
return list;
}
-static GSList*
-conn_get_table_list_pgsql (dbi_conn conn, const gchar* dbname)
+template<> std::vector<std::string>
+GncDbiProviderImpl<DbType::DBI_MYSQL>::get_table_list (dbi_conn conn,
+ const std::string& dbname)
{
- gboolean change_made;
-
- /* Return the list, but remove the tables that postgresql adds from the information schema. */
- GSList* list = conn_get_table_list (conn, dbname);
- change_made = TRUE;
- while (list != nullptr && change_made)
- {
- GSList* node;
+ return conn_get_table_list (conn, dbname);
+}
- change_made = FALSE;
- for (node = list; node != nullptr; node = node->next)
- {
- const gchar* table_name = (const gchar*)node->data;
-
- if (strcmp (table_name, "sql_features") == 0 ||
- strcmp (table_name, "sql_implementation_info") == 0 ||
- strcmp (table_name, "sql_languages") == 0 ||
- strcmp (table_name, "sql_packages") == 0 ||
- strcmp (table_name, "sql_parts") == 0 ||
- strcmp (table_name, "sql_sizing") == 0 ||
- strcmp (table_name, "sql_sizing_profiles") == 0)
- {
- g_free (node->data);
- list = g_slist_delete_link (list, node);
- change_made = TRUE;
- break;
- }
- }
- }
+template<> std::vector<std::string>
+GncDbiProviderImpl<DbType::DBI_PGSQL>::get_table_list (dbi_conn conn,
+ const std::string& dbname)
+{
+ auto list = conn_get_table_list (conn, dbname);
+ auto end = std::remove_if (list.begin(), list.end(),
+ [](std::string& table_name){
+ return table_name == "sql_features" ||
+ table_name == "sql_implementation_info" ||
+ table_name == "sql_languages" ||
+ table_name == "sql_packages" ||
+ table_name == "sql_parts" ||
+ table_name == "sql_sizing" ||
+ table_name == "sql_sizing_profiles";
+ });
+ list.erase(end, list.end());
return list;
}
diff --git a/src/backend/dbi/gnc-backend-dbi.hpp b/src/backend/dbi/gnc-backend-dbi.hpp
index d265bb3..cba8732 100644
--- a/src/backend/dbi/gnc-backend-dbi.hpp
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -28,13 +28,6 @@ extern "C"
}
#include "gnc-backend-sql.h"
-enum class DbType
-{
- DBI_SQLITE,
- DBI_MYSQL,
- DBI_PGSQL
-};
-
/**
* Options to conn_table_operation
* @var drop Drop (remove without recourse) the table from the database
@@ -65,27 +58,25 @@ typedef enum
GNC_DBI_FAIL_TEST
} GncDbiTestResult;
-typedef gchar* (*CREATE_TABLE_DDL_FN) (const GncSqlConnection* conn,
- const gchar* table_name,
- const ColVec& info_vec);
-typedef GSList* (*GET_TABLE_LIST_FN) (dbi_conn conn, const gchar* dbname);
-typedef void (*APPEND_COLUMN_DEF_FN) (GString* ddl,
- const GncSqlColumnInfo& info);
-typedef GSList* (*GET_INDEX_LIST_FN) (dbi_conn conn);
-typedef void (*DROP_INDEX_FN) (dbi_conn conn, const gchar* index);
-typedef struct
+class GncDbiProvider
{
- CREATE_TABLE_DDL_FN create_table_ddl;
- GET_TABLE_LIST_FN get_table_list;
- APPEND_COLUMN_DEF_FN append_col_def;
- GET_INDEX_LIST_FN get_index_list;
- DROP_INDEX_FN drop_index;
-} provider_functions_t;
+public:
+ virtual ~GncDbiProvider() = default;
+ virtual std::string create_table_ddl(const GncSqlConnection* conn,
+ const std::string& table_name,
+ const ColVec& info_vec) = 0;
+ virtual std::vector<std::string> get_table_list(dbi_conn conn,
+ const std::string& dbname) = 0;
+ virtual void append_col_def(std::string& ddl,
+ const GncSqlColumnInfo& info) = 0;
+ virtual std::vector<std::string> get_index_list (dbi_conn conn) = 0;
+ virtual void drop_index(dbi_conn conn, const std::string& index) = 0;
+};
/**
* Implementations of GncSqlBackend.
*/
-struct GncDbiBackend_struct
+struct GncDbiBackend
{
GncSqlBackend sql_be;
@@ -103,16 +94,14 @@ struct GncDbiBackend_struct
// GHashTable* versions; // Version number for each table
};
-typedef struct GncDbiBackend_struct GncDbiBackend;
-
class GncDbiSqlConnection : public GncSqlConnection
{
public:
- GncDbiSqlConnection (provider_functions_t* provider, QofBackend* qbe,
+ GncDbiSqlConnection (GncDbiProvider* provider, QofBackend* qbe,
dbi_conn conn) :
m_qbe{qbe}, m_conn{conn}, m_provider{provider}, m_conn_ok{true},
m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0}, m_retry{false} {}
- ~GncDbiSqlConnection() override = default;
+ ~GncDbiSqlConnection() override { delete m_provider; };
GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
noexcept override;
int execute_nonselect_statement (const GncSqlStatementPtr&)
@@ -131,7 +120,7 @@ public:
std::string quote_string (const std::string&) const noexcept override;
QofBackend* qbe () const noexcept { return m_qbe; }
dbi_conn conn() const noexcept { return m_conn; }
- provider_functions_t* provider() { return m_provider; }
+ GncDbiProvider* provider() { return m_provider; }
inline void set_error (int error, int repeat, bool retry) noexcept
{
m_last_error = error;
@@ -151,17 +140,17 @@ public:
/* FIXME: These three friend functions should really be members, but doing
* that is too invasive just yet. */
friend gboolean conn_table_operation (GncSqlConnection* sql_conn,
- GSList* table_name_list,
+ std::vector<std::string> table_name_list,
TableOpType op);
friend void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
- friend gchar* add_columns_ddl(const GncSqlConnection* conn,
- const gchar* table_name,
- const ColVec& info_vec);
+ friend std::string add_columns_ddl(const GncSqlConnection* conn,
+ const std::string& table_name,
+ const ColVec& info_vec);
private:
QofBackend* m_qbe;
dbi_conn m_conn;
- provider_functions_t* m_provider;
+ GncDbiProvider* m_provider;
/** Used by the error handler routines to flag if the connection is ok to
* use
*/
@@ -186,8 +175,9 @@ private:
gboolean conn_table_operation (GncSqlConnection* sql_conn,
GSList* table_name_list, TableOpType op);
void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
-gchar* add_columns_ddl(const GncSqlConnection* conn, const gchar* table_name,
- const ColVec& info_vec);
+std::string add_columns_ddl(const GncSqlConnection* conn,
+ const std::string& table_name,
+ const ColVec& info_vec);
/* external access required for tests */
std::string adjust_sql_options_string(const std::string&);
diff --git a/src/backend/dbi/test/test-backend-dbi-basic.cpp b/src/backend/dbi/test/test-backend-dbi-basic.cpp
index e09489e..73f60d6 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.cpp
+++ b/src/backend/dbi/test/test-backend-dbi-basic.cpp
@@ -357,21 +357,17 @@ test_conn_index_functions (QofBackend* qbe)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (be->sql_be.conn);
- GSList* index_list, *iter;
- index_list = conn->provider()->get_index_list (be->conn);
+ auto index_list = conn->provider()->get_index_list (be->conn);
g_test_message ("Returned from index list\n");
- g_assert (index_list != NULL);
- g_assert_cmpint (g_slist_length (index_list), == , 4);
- for (iter = index_list; iter != NULL; iter = g_slist_next (iter))
+ g_assert_cmpint (index_list.size(), == , 4);
+ for (auto index : index_list)
{
const char* errmsg;
- conn->provider()->drop_index (be->conn,
- static_cast<const char*> (iter->data));
+ conn->provider()->drop_index (be->conn, index);
g_assert (DBI_ERROR_NONE == dbi_conn_error (conn->conn(), &errmsg));
}
- g_slist_free (index_list);
}
/* Given a synthetic session, use the same logic as
diff --git a/src/backend/dbi/test/test-dbi-stuff.cpp b/src/backend/dbi/test/test-dbi-stuff.cpp
index ad5e81d..3895039 100644
--- a/src/backend/dbi/test/test-dbi-stuff.cpp
+++ b/src/backend/dbi/test/test-dbi-stuff.cpp
@@ -216,23 +216,16 @@ test_conn_index_functions (QofBackend* qbe)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (be->sql_be.conn);
- GSList* index_list, *iter;
- index_list = conn->provider()->get_index_list (be->conn);
+ auto index_list = conn->provider()->get_index_list (be->conn);
g_test_message ("Returned from index list\n");
- g_assert (index_list != NULL);
- g_assert_cmpint (g_slist_length (index_list), == , 4);
- for (iter = index_list; iter != NULL; iter = g_slist_next (iter))
+ g_assert_cmpint (index_list.size(), == , 4);
+ for (auto index : index_list)
{
const char* errmsg;
- conn->provider()->drop_index (be->conn,
- static_cast<const char*> (iter->data));
+ conn->provider()->drop_index (be->conn, index);
g_assert (DBI_ERROR_NONE == dbi_conn_error (conn->conn(), &errmsg));
}
-
- g_slist_free (index_list);
-
-
}
static void
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 39b73d3..334199d 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -78,7 +78,6 @@ struct GncSqlBackend
GHashTable* versions; /**< Version number for each table */
const gchar* timespec_format; /**< Format string for SQL for timespec values */
};
-typedef struct GncSqlBackend GncSqlBackend;
/**
* Initialize the SQL backend.
commit faf59964e4e4b92a422dd50305c24874de975d63
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jul 16 12:12:03 2016 -0700
Rename gnc-backend-dbi-priv.h to gnc-backend-dbi.hpp.
Also remove "#ifdef __cplusplus" from both gnc-backend-dbi.hpp and
gnc-backend-dbi.h, these files are always C++.
diff --git a/src/backend/dbi/gnc-backend-dbi.h b/src/backend/dbi/gnc-backend-dbi.h
index d836d6e..7d769ae 100644
--- a/src/backend/dbi/gnc-backend-dbi.h
+++ b/src/backend/dbi/gnc-backend-dbi.h
@@ -28,10 +28,8 @@
#ifndef GNC_BACKEND_DBI_H_
#define GNC_BACKEND_DBI_H_
-#ifdef __cplusplus
extern "C"
{
-#endif
#include <gmodule.h>
/** Initialization function which can be used when this module is
@@ -48,7 +46,5 @@ void gnc_module_finalize_backend_dbi (void);
G_MODULE_EXPORT void qof_backend_module_init (void);
G_MODULE_EXPORT void qof_backend_module_finalize (void);
#endif
-#ifdef __cplusplus
}
-#endif
#endif /* GNC_BACKEND_DBI_H_ */
diff --git a/src/backend/dbi/gnc-backend-dbi-priv.h b/src/backend/dbi/gnc-backend-dbi.hpp
similarity index 97%
rename from src/backend/dbi/gnc-backend-dbi-priv.h
rename to src/backend/dbi/gnc-backend-dbi.hpp
index 41d46f1..d265bb3 100644
--- a/src/backend/dbi/gnc-backend-dbi-priv.h
+++ b/src/backend/dbi/gnc-backend-dbi.hpp
@@ -1,5 +1,5 @@
/********************************************************************
- * gnc-backend-dbi-priv.h: load and save data to SQL via libdbi *
+ * gnc-backend-dbi.hpp: load and save data to SQL via libdbi *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@@ -20,16 +20,12 @@
\********************************************************************/
/* Private structures and variables for gnc-backend-dbi.c and its unit tests */
-#ifndef GNC_BACKEND_DBI_PRIV_H
-#define GNC_BACKEND_DBI_PRIV_H
-#ifdef __cplusplus
+#ifndef GNC_BACKEND_DBI_HPP
+#define GNC_BACKEND_DBI_HPP
extern "C"
{
-#endif
#include <dbi/dbi.h>
-#ifdef __cplusplus
}
-#endif
#include "gnc-backend-sql.h"
enum class DbType
@@ -239,4 +235,4 @@ private:
};
-#endif //GNC_BACKEND_DBI_PRIV_H
+#endif //GNC_BACKEND_DBI_HPP
diff --git a/src/backend/dbi/test/test-backend-dbi-basic.cpp b/src/backend/dbi/test/test-backend-dbi-basic.cpp
index 41c4f8c..e09489e 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.cpp
+++ b/src/backend/dbi/test/test-backend-dbi-basic.cpp
@@ -51,7 +51,7 @@ extern "C"
#include <gnc-prefs.h>
}
/* For test_conn_index_functions */
-#include "../gnc-backend-dbi-priv.h"
+#include "../gnc-backend-dbi.hpp"
extern "C"
{
#include <unittest-support.h>
diff --git a/src/backend/dbi/test/test-dbi-stuff.cpp b/src/backend/dbi/test/test-dbi-stuff.cpp
index c04af87..ad5e81d 100644
--- a/src/backend/dbi/test/test-dbi-stuff.cpp
+++ b/src/backend/dbi/test/test-dbi-stuff.cpp
@@ -39,7 +39,7 @@ extern "C"
}
#include <kvp_frame.hpp>
-#include "../gnc-backend-dbi-priv.h"
+#include "../gnc-backend-dbi.hpp"
G_GNUC_UNUSED static QofLogModule log_module = "test-dbi";
commit 7fe404808ade6e8ea74aae55e2ddabd903857282
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Jul 3 17:06:19 2016 -0700
Delete some no-longer (or in some cases never) used functions.
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index ba0da85..be0338d 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -193,15 +193,9 @@ create_tables(const OBEEntry& entry, GncSqlBackend* be)
static const StrVec fixed_load_order
{ GNC_ID_BOOK, GNC_ID_COMMODITY, GNC_ID_ACCOUNT, GNC_ID_LOT };
-
-/* Load order for objects from other modules */
-static StrVec other_load_order;
-
-void
-gnc_sql_set_load_order(const StrVec& load_order)
-{
- other_load_order = load_order;
-}
+/* 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* be)
@@ -216,8 +210,8 @@ initial_load(const OBEEntry& entry, GncSqlBackend* be)
*/
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;
+ if (std::find(business_fixed_load_order.begin(), business_fixed_load_order.end(),
+ type) != business_fixed_load_order.end()) return;
obe->load_all (be);
}
@@ -263,7 +257,7 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
obe->load_all (be);
}
}
- for (auto type : other_load_order)
+ for (auto type : business_fixed_load_order)
{
auto obe = gnc_sql_get_object_backend(type);
if (obe)
@@ -1031,9 +1025,6 @@ gnc_sql_run_query (QofBackend* pBEnd, gpointer pQuery)
}
#endif //if 0: query creation isn't used yet, code never tested.
/* ================================================================= */
-/* 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
business_core_sql_init (void)
@@ -1048,8 +1039,6 @@ business_core_sql_init (void)
gnc_order_sql_initialize ();
gnc_taxtable_sql_initialize ();
gnc_vendor_sql_initialize ();
-
- gnc_sql_set_load_order (business_fixed_load_order);
}
static void
@@ -1071,49 +1060,6 @@ gnc_sql_init_object_handlers (void)
}
/* ================================================================= */
-
-gint64
-gnc_sql_get_integer_value (const GValue* value)
-{
- g_return_val_if_fail (value != NULL, 0);
-
- if (G_VALUE_HOLDS_INT (value))
- {
- return (gint64)g_value_get_int (value);
- }
- else if (G_VALUE_HOLDS_UINT (value))
- {
- return (gint64)g_value_get_uint (value);
- }
- else if (G_VALUE_HOLDS_LONG (value))
- {
- return (gint64)g_value_get_long (value);
- }
- else if (G_VALUE_HOLDS_ULONG (value))
- {
- return (gint64)g_value_get_ulong (value);
- }
- else if (G_VALUE_HOLDS_INT64 (value))
- {
- return g_value_get_int64 (value);
- }
- else if (G_VALUE_HOLDS_UINT64 (value))
- {
- return (gint64)g_value_get_uint64 (value);
- }
- else if (G_VALUE_HOLDS_STRING (value))
- {
- return g_ascii_strtoll (g_value_get_string (value), NULL, 10);
- }
- else
- {
- PWARN ("Unknown type: %s", G_VALUE_TYPE_NAME (value));
- }
-
- return 0;
-}
-
-/* ----------------------------------------------------------------- */
static gpointer
get_autoinc_id (void* object, const QofParam* param)
{
@@ -1805,19 +1751,6 @@ static EntryVec tx_guid_table
gnc_sql_make_table_entry<CT_GUID>("tx_guid", 0, 0, nullptr, _retrieve_guid_)
};
-
-const GncGUID*
-gnc_sql_load_tx_guid (const GncSqlBackend* be, GncSqlRow& row)
-{
- static GncGUID guid;
-
- g_return_val_if_fail (be != NULL, NULL);
-
- gnc_sql_load_object (be, row, NULL, &guid, tx_guid_table);
-
- return &guid;
-}
-
void
gnc_sql_load_object (const GncSqlBackend* be, GncSqlRow& row,
QofIdTypeConst obj_name, gpointer pObject,
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 7f145bc..39b73d3 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -881,16 +881,6 @@ gboolean gnc_sql_create_index (const GncSqlBackend* be, const char* index_name,
const GncGUID* gnc_sql_load_guid (const GncSqlBackend* be, GncSqlRow& row);
-/**
- * Loads the transaction guid from a database row. The table must have a column
- * named "tx_guid" with type CT_GUID.
- *
- * @param be SQL backend struct
- * @param row Database row
- * @return GncGUID
- */
-
-const GncGUID* gnc_sql_load_tx_guid (const GncSqlBackend* be, GncSqlRow& row);
/**
* Creates a basic SELECT statement for a table.
@@ -928,30 +918,6 @@ void gnc_sql_init_version_info (GncSqlBackend* be);
void gnc_sql_finalize_version_info (GncSqlBackend* be);
/**
- * Commits a "standard" item to the database. In most cases, a commit of one
- * object vs another differs only in the table name and column table.
- *
- * @param be SQL backend
- * @param inst Instance
- * @param tableName SQL table name
- * @param obj_name QOF object type name
- * @param col_table Column table
- * @return TRUE if successful, FALSE if not
- */
-gboolean gnc_sql_commit_standard_item (GncSqlBackend* be, QofInstance* inst,
- const gchar* tableName,
- QofIdTypeConst obj_name,
- const EntryVec& col_table);
-
-/**
- * Gets an integer value (of any size) from a GValue.
- *
- * @param value Source value
- * @return Integer value
- */
-gint64 gnc_sql_get_integer_value (const GValue* value);
-
-/**
* Converts a Timespec value to a string value for the database.
*
* @param be SQL backend
@@ -986,15 +952,6 @@ void gnc_sql_upgrade_table (GncSqlBackend* be, const gchar* table_name,
gboolean gnc_sql_add_columns_to_table (GncSqlBackend* be, const char* table_name,
const EntryVec& new_col_table);
-/**
- * Specifies the load order for a set of objects. When loading from a database,
- * the objects will be loaded in this order, so that when later objects have
- * references to objects, those objects will already have been loaded.
- *
- * @param load_order NULL-terminated array of object type ID strings
- */
-void gnc_sql_set_load_order(StrVec&& load_order);
-
void _retrieve_guid_ (gpointer pObject, gpointer pValue);
gpointer gnc_sql_compile_query (QofBackend* pBEnd, QofQuery* pQuery);
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index fbbe460..3dc7ea4 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -123,14 +123,6 @@ create_tables_cb (const gchar* type, gpointer data_p, gpointer be_p)// 2
test_create_tables_cb (Fixture *fixture, gconstpointer pData)
{
}*/
-/* gnc_sql_set_load_order
-void
-gnc_sql_set_load_order (const gchar** load_order)// 2
-*/
-/* static void
-test_gnc_sql_set_load_order (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* initial_load_cb
static void
initial_load_cb (const gchar* type, gpointer data_p, gpointer be_p)// 2
@@ -428,13 +420,6 @@ gnc_sql_init_object_handlers (void)// 3
test_gnc_sql_init_object_handlers (Fixture *fixture, gconstpointer pData)
{
}*/
-/* gnc_sql_get_integer_value
-gint64
-gnc_sql_get_integer_value (const GValue* value)// C: 1 */
-/* static void
-test_gnc_sql_get_integer_value (Fixture *fixture, gconstpointer pData)
-{
-}*/
// Make Static
/* get_autoinc_id
get_autoinc_id()// 2
@@ -784,15 +769,6 @@ gnc_sql_load_guid (const GncSqlBackend* be, GncSqlRow& row)// C: 15 in 14 */
test_gnc_sql_load_guid (Fixture *fixture, gconstpointer pData)
{
}*/
-// Not Used
-/* gnc_sql_load_tx_guid
-const GncGUID*
-gnc_sql_load_tx_guid (const GncSqlBackend* be, GncSqlRow& row)// 1
-*/
-/* static void
-test_gnc_sql_load_tx_guid (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* gnc_sql_load_object
void
gnc_sql_load_object (const GncSqlBackend* be, GncSqlRow& row,// C: 29 in 19 */
@@ -915,13 +891,6 @@ build_delete_statement (GncSqlBackend* be,// 3
test_build_delete_statement (Fixture *fixture, gconstpointer pData)
{
}*/
-/* gnc_sql_commit_standard_item
-gboolean
-gnc_sql_commit_standard_item (GncSqlBackend* be, QofInstance* inst, const gchar* tableName,// C: 7 in 7 */
-/* static void
-test_gnc_sql_commit_standard_item (Fixture *fixture, gconstpointer pData)
-{
-}*/
/* do_create_table
static gboolean
do_create_table (const GncSqlBackend* be, const gchar* table_name,// 5
@@ -1010,7 +979,6 @@ test_suite_gnc_backend_sql (void)
// GNC_TEST_ADD (suitename, "gnc sql init", Fixture, nullptr, test_gnc_sql_init, teardown);
// GNC_TEST_ADD (suitename, "create tables cb", Fixture, nullptr, test_create_tables_cb, teardown);
-// GNC_TEST_ADD (suitename, "gnc sql set load order", Fixture, nullptr, test_gnc_sql_set_load_order, teardown);
// GNC_TEST_ADD (suitename, "initial load cb", Fixture, nullptr, test_initial_load_cb, teardown);
// GNC_TEST_ADD (suitename, "gnc sql load", Fixture, nullptr, test_gnc_sql_load, teardown);
// GNC_TEST_ADD (suitename, "write account tree", Fixture, nullptr, test_write_account_tree, teardown);
@@ -1038,7 +1006,6 @@ test_suite_gnc_backend_sql (void)
// GNC_TEST_ADD (suitename, "gnc sql run query", Fixture, nullptr, test_gnc_sql_run_query, teardown);
// GNC_TEST_ADD (suitename, "business core sql init", Fixture, nullptr, test_business_core_sql_init, teardown);
// GNC_TEST_ADD (suitename, "gnc sql init object handlers", Fixture, nullptr, test_gnc_sql_init_object_handlers, teardown);
-// GNC_TEST_ADD (suitename, "gnc sql get integer value", Fixture, nullptr, test_gnc_sql_get_integer_value, teardown);
// GNC_TEST_ADD (suitename, "get autoinc id", Fixture, nullptr, test_get_autoinc_id, teardown);
// GNC_TEST_ADD (suitename, "set autoinc id", Fixture, nullptr, test_set_autoinc_id, teardown);
// GNC_TEST_ADD (suitename, "gnc sql get getter", Fixture, nullptr, test_gnc_sql_get_getter, teardown);
@@ -1098,7 +1065,6 @@ test_suite_gnc_backend_sql (void)
// GNC_TEST_ADD (suitename, "build insert statement", Fixture, nullptr, test_build_insert_statement, teardown);
// GNC_TEST_ADD (suitename, "build update statement", Fixture, nullptr, test_build_update_statement, teardown);
// GNC_TEST_ADD (suitename, "build delete statement", Fixture, nullptr, test_build_delete_statement, teardown);
-// GNC_TEST_ADD (suitename, "gnc sql commit standard item", Fixture, nullptr, test_gnc_sql_commit_standard_item, teardown);
// GNC_TEST_ADD (suitename, "do create table", Fixture, nullptr, test_do_create_table, teardown);
// GNC_TEST_ADD (suitename, "gnc sql create table", Fixture, nullptr, test_gnc_sql_create_table, teardown);
// GNC_TEST_ADD (suitename, "gnc sql create temp table", Fixture, nullptr, test_gnc_sql_create_temp_table, teardown);
commit cfa3ab24f68250c6f04b158763874715826ffa09
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jun 18 12:40:28 2016 -0700
Convert GncSqlConnection to a C++ class.
diff --git a/src/backend/dbi/gnc-backend-dbi-priv.h b/src/backend/dbi/gnc-backend-dbi-priv.h
index 0743771..41d46f1 100644
--- a/src/backend/dbi/gnc-backend-dbi-priv.h
+++ b/src/backend/dbi/gnc-backend-dbi-priv.h
@@ -32,6 +32,13 @@ extern "C"
#endif
#include "gnc-backend-sql.h"
+enum class DbType
+{
+ DBI_SQLITE,
+ DBI_MYSQL,
+ DBI_PGSQL
+};
+
/**
* Options to conn_table_operation
* @var drop Drop (remove without recourse) the table from the database
@@ -62,7 +69,7 @@ typedef enum
GNC_DBI_FAIL_TEST
} GncDbiTestResult;
-typedef gchar* (*CREATE_TABLE_DDL_FN) (GncSqlConnection* conn,
+typedef gchar* (*CREATE_TABLE_DDL_FN) (const GncSqlConnection* conn,
const gchar* table_name,
const ColVec& info_vec);
typedef GSList* (*GET_TABLE_LIST_FN) (dbi_conn conn, const gchar* dbname);
@@ -79,7 +86,9 @@ typedef struct
DROP_INDEX_FN drop_index;
} provider_functions_t;
-
+/**
+ * Implementations of GncSqlBackend.
+ */
struct GncDbiBackend_struct
{
GncSqlBackend sql_be;
@@ -100,22 +109,90 @@ struct GncDbiBackend_struct
typedef struct GncDbiBackend_struct GncDbiBackend;
-typedef struct
+class GncDbiSqlConnection : public GncSqlConnection
{
- GncSqlConnection base;
+public:
+ GncDbiSqlConnection (provider_functions_t* provider, QofBackend* qbe,
+ dbi_conn conn) :
+ m_qbe{qbe}, m_conn{conn}, m_provider{provider}, m_conn_ok{true},
+ m_last_error{ERR_BACKEND_NO_ERR}, m_error_repeat{0}, m_retry{false} {}
+ ~GncDbiSqlConnection() override = default;
+ GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
+ noexcept override;
+ int execute_nonselect_statement (const GncSqlStatementPtr&)
+ noexcept override;
+ GncSqlStatementPtr create_statement_from_sql (const std::string&)
+ const noexcept override;
+ bool does_table_exist (const std::string&) const noexcept override;
+ bool begin_transaction () noexcept override;
+ bool rollback_transaction () const noexcept override;
+ bool commit_transaction () const noexcept override;
+ bool create_table (const std::string&, const ColVec&) const noexcept override;
+ bool create_index (const std::string&, const std::string&, const EntryVec&)
+ const noexcept override;
+ bool add_columns_to_table (const std::string&, const ColVec&)
+ const noexcept override;
+ std::string quote_string (const std::string&) const noexcept override;
+ QofBackend* qbe () const noexcept { return m_qbe; }
+ dbi_conn conn() const noexcept { return m_conn; }
+ provider_functions_t* provider() { return m_provider; }
+ inline void set_error (int error, int repeat, bool retry) noexcept
+ {
+ m_last_error = error;
+ m_error_repeat = repeat;
+ m_retry = retry;
+ }
+ inline void init_error () noexcept
+ {
+ set_error(ERR_BACKEND_NO_ERR, 0, false);
+ }
+ /** Check if the dbi connection is valid. If not attempt to re-establish it
+ * Returns TRUE is there is a valid connection in the end or FALSE otherwise
+ */
+ bool verify() noexcept;
+ bool retry_connection(const char* msg) noexcept;
+ dbi_result table_manage_backup(const std::string& table_name, TableOpType op);
+ /* FIXME: These three friend functions should really be members, but doing
+ * that is too invasive just yet. */
+ friend gboolean conn_table_operation (GncSqlConnection* sql_conn,
+ GSList* table_name_list,
+ TableOpType op);
+ friend void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
+ friend gchar* add_columns_ddl(const GncSqlConnection* conn,
+ const gchar* table_name,
+ const ColVec& info_vec);
+
+private:
+ QofBackend* m_qbe;
+ dbi_conn m_conn;
+ provider_functions_t* m_provider;
+ /** Used by the error handler routines to flag if the connection is ok to
+ * use
+ */
+ bool m_conn_ok;
+ /** Code of the last error that occurred. This is set in the error callback
+ * function.
+ */
+ int m_last_error;
+ /** Used in case of transient errors. After such error, another attempt at
+ * the original call is allowed. error_repeat tracks the number of attempts
+ * and can be used to prevent infinite loops.
+ */
+ int m_error_repeat;
+ /** Signals the calling function that it should retry (the error handler
+ * detected transient error and managed to resolve it, but it can't run the
+ * original query)
+ */
+ gboolean m_retry;
+
+};
+
+gboolean conn_table_operation (GncSqlConnection* sql_conn,
+ GSList* table_name_list, TableOpType op);
+void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book);
+gchar* add_columns_ddl(const GncSqlConnection* conn, const gchar* table_name,
+ const ColVec& info_vec);
- QofBackend* qbe;
- dbi_conn conn;
- provider_functions_t* provider;
- gboolean conn_ok; // Used by the error handler routines to flag if the connection is ok to use
- gint last_error; // Code of the last error that occurred. This is set in the error callback function
- gint error_repeat; // Used in case of transient errors. After such error, another attempt at the
- // original call is allowed. error_repeat tracks the number of attempts and can
- // be used to prevent infinite loops.
- gboolean retry; // Signals the calling function that it should retry (the error handler detected
- // transient error and managed to resolve it, but it can't run the original query)
-
-} GncDbiSqlConnection;
/* external access required for tests */
std::string adjust_sql_options_string(const std::string&);
@@ -123,7 +200,7 @@ std::string adjust_sql_options_string(const std::string&);
class GncDbiSqlResult : public GncSqlResult
{
public:
- GncDbiSqlResult(GncDbiSqlConnection* conn, dbi_result result) :
+ GncDbiSqlResult(const GncDbiSqlConnection* conn, dbi_result result) :
m_conn{conn}, m_dbi_result{result}, m_iter{this}, m_row{&m_iter},
m_sentinel{nullptr} {}
~GncDbiSqlResult();
@@ -153,7 +230,7 @@ protected:
GncDbiSqlResult* m_inst;
};
private:
- GncDbiSqlConnection* m_conn;
+ const GncDbiSqlConnection* m_conn;
dbi_result m_dbi_result;
IteratorImpl m_iter;
GncSqlRow m_row;
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index e1c82f9..cabd8a4 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -157,7 +157,7 @@ static gchar lock_table[] = "gnclock";
#define SQLITE3_URI_PREFIX (SQLITE3_URI_TYPE "://")
#define PGSQL_DEFAULT_PORT 5432
-static gchar* conn_create_table_ddl_sqlite3 (GncSqlConnection* conn,
+static gchar* conn_create_table_ddl_sqlite3 (const GncSqlConnection* conn,
const gchar* table_name,
const ColVec& info_vec);
static GSList* conn_get_table_list (dbi_conn conn, const gchar* dbname);
@@ -175,7 +175,7 @@ static provider_functions_t provider_sqlite3 =
};
#define SQLITE3_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
-static gchar* conn_create_table_ddl_mysql (GncSqlConnection* conn,
+static gchar* conn_create_table_ddl_mysql (const GncSqlConnection* conn,
const gchar* table_name,
const ColVec& info_vec);
static void append_mysql_col_def (GString* ddl, const GncSqlColumnInfo& info);
@@ -191,7 +191,7 @@ static provider_functions_t provider_mysql =
};
#define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
-static gchar* conn_create_table_ddl_pgsql (GncSqlConnection* conn,
+static gchar* conn_create_table_ddl_pgsql (const GncSqlConnection* conn,
const gchar* table_name,
const ColVec& info_vec );
static GSList* conn_get_table_list_pgsql (dbi_conn conn, const gchar* dbname);
@@ -213,15 +213,10 @@ static gboolean gnc_dbi_lock_database (QofBackend *qbe, gboolean ignore_lock);
static void gnc_dbi_unlock (QofBackend *qbe);
static gboolean save_may_clobber_data (QofBackend* qbe);
-static gchar* create_index_ddl (GncSqlConnection* conn,
+static gchar* create_index_ddl (const GncSqlConnection* conn,
const gchar* index_name,
const gchar* table_name,
const EntryVec& col_table);
-static gchar* add_columns_ddl (GncSqlConnection* conn,
- const gchar* table_name,
- const ColVec& info_vec);
-static GncSqlConnection* create_dbi_connection (provider_functions_t* provider,
- QofBackend* qbe, dbi_conn conn);
static GncDbiTestResult conn_test_dbi_library (dbi_conn conn);
#define GNC_DBI_PROVIDER_SQLITE (&provider_sqlite3)
#define GNC_DBI_PROVIDER_MYSQL (&provider_mysql)
@@ -245,45 +240,54 @@ gnc_table_slist_free (GSList* table_list)
g_slist_free (table_list);
}
-static void
-gnc_dbi_set_error (GncDbiSqlConnection* dbi_conn, gint last_error,
- gint error_repeat, gboolean retry)
-{
- g_return_if_fail (dbi_conn != nullptr);
-
- dbi_conn->last_error = last_error;
- if (error_repeat > 0)
- dbi_conn->error_repeat = dbi_conn->error_repeat + error_repeat;
- else
- dbi_conn->error_repeat = 0;
- dbi_conn->retry = retry;
-}
-
-static void
-gnc_dbi_init_error (GncDbiSqlConnection* dbi_conn)
-{
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_NO_ERR, 0, FALSE);
-}
-
/* Check if the dbi connection is valid. If not attempt to re-establish it
* Returns TRUE is there is a valid connection in the end or FALSE otherwise
*/
-static gboolean
-gnc_dbi_verify_conn (GncDbiSqlConnection* dbi_conn)
+bool
+GncDbiSqlConnection::verify () noexcept
{
- if (dbi_conn->conn_ok)
- return TRUE;
+ if (m_conn_ok)
+ return true;
- /* We attempt to connect only once here. The error function will automatically
- * re-attempt up until DBI_MAX_CONN_ATTEMPTS time to connect if this call fails.
- * After all these attempts, conn_ok will indicate if there is a valid connection
- * or not.
+ /* We attempt to connect only once here. The error function will
+ * automatically re-attempt up until DBI_MAX_CONN_ATTEMPTS time to connect
+ * if this call fails. After all these attempts, conn_ok will indicate if
+ * there is a valid connection or not.
*/
- gnc_dbi_init_error (dbi_conn);
- dbi_conn->conn_ok = TRUE;
- (void)dbi_conn_connect (dbi_conn->conn);
+ init_error ();
+ m_conn_ok = true;
+ (void)dbi_conn_connect (m_conn);
- return dbi_conn->conn_ok;
+ return m_conn_ok;
+}
+
+bool
+GncDbiSqlConnection::retry_connection(const char* msg)
+ noexcept
+{
+ while (m_retry && m_error_repeat <= DBI_MAX_CONN_ATTEMPTS)
+ {
+ m_conn_ok = false;
+ if (dbi_conn_connect(m_conn) == 0)
+ {
+ init_error();
+ m_conn_ok = true;
+ return true;
+ }
+#ifdef G_OS_WIN32
+ const guint backoff_msecs = 1;
+ Sleep (backoff_msecs * 2 << ++m_error_repeat);
+#else
+ const guint backoff_usecs = 1000;
+ usleep (backoff_usecs * 2 << ++m_error_repeat);
+#endif
+ PINFO ("DBI error: %s - Reconnecting...\n", msg);
+
+ }
+ PERR ("DBI error: %s - Giving up after %d consecutive attempts.\n", msg,
+ DBI_MAX_CONN_ATTEMPTS);
+ m_conn_ok = false;
+ return false;
}
/* ================================================================= */
@@ -304,13 +308,12 @@ sqlite3_error_fn (dbi_conn conn, void* user_data)
{
const gchar* msg;
GncDbiBackend *be = static_cast<decltype(be)>(user_data);
-/* FIXME: Cast won't be necessary once GncDbiSqlConnection is a derived class of
- * GncSqlConnection. */
+/* FIXME: GncSqlConnection doesn't have the error calls so we have to dynamic_cast from the connection stored in GncSqlBackend. Yuck. */
GncDbiSqlConnection *dbi_conn =
- reinterpret_cast<decltype(dbi_conn)>(be->sql_be.conn);
- (void)dbi_conn_error(conn, &msg);
- PERR( "DBI error: %s\n", msg );
- gnc_dbi_set_error(dbi_conn, ERR_BACKEND_MISC, 0, FALSE);
+ dynamic_cast<decltype(dbi_conn)>(be->sql_be.conn);
+ int errnum = dbi_conn_error (conn, &msg);
+ PERR ("DBI error: %s\n", msg);
+ dbi_conn->set_error (ERR_BACKEND_MISC, 0, false);
}
static void
@@ -449,9 +452,9 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
if (be->sql_be.conn != nullptr)
{
- gnc_sql_connection_dispose (be->sql_be.conn);
+ delete (be->sql_be.conn);
}
- be->sql_be.conn = create_dbi_connection (GNC_DBI_PROVIDER_SQLITE, qbe,
+ be->sql_be.conn = new GncDbiSqlConnection (GNC_DBI_PROVIDER_SQLITE, qbe,
be->conn);
be->sql_be.timespec_format = SQLITE3_TIMESPEC_STR_FORMAT;
@@ -502,16 +505,11 @@ static void
mysql_error_fn (dbi_conn conn, void* user_data)
{
GncDbiBackend* be = (GncDbiBackend*)user_data;
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)be->sql_be.conn;
- const gchar* msg;
- gint err_num;
-#ifdef G_OS_WIN32
- const guint backoff_msecs = 1;
-#else
- const guint backoff_usecs = 1000;
-#endif
+ GncDbiSqlConnection* dbi_conn =
+ dynamic_cast<decltype(dbi_conn)>(be->sql_be.conn);
+ const char* msg;
- err_num = dbi_conn_error (conn, &msg);
+ auto err_num = dbi_conn_error (conn, &msg);
/* Note: the sql connection may not have been initialized yet
* so let's be careful with using it
@@ -543,39 +541,19 @@ mysql_error_fn (dbi_conn conn, void* user_data)
{
PINFO ("DBI error: %s - Reconnecting...\n", msg);
if (dbi_conn)
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_CONN_LOST, 1, TRUE);
- dbi_conn->conn_ok = TRUE;
- (void)dbi_conn_connect (conn);
+ dbi_conn->set_error (ERR_BACKEND_CONN_LOST, 1, true);
+ dbi_conn->retry_connection(msg);
}
else if (err_num == 2003) // Unable to connect
{
- if (dbi_conn->error_repeat >= DBI_MAX_CONN_ATTEMPTS)
- {
- PERR ("DBI error: %s - Giving up after %d consecutive attempts.\n", msg,
- DBI_MAX_CONN_ATTEMPTS);
- if (dbi_conn)
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_CANT_CONNECT, 0, FALSE);
- dbi_conn->conn_ok = FALSE;
- }
- else
- {
-#ifdef G_OS_WIN32
- Sleep (backoff_msecs * 2 << dbi_conn->error_repeat);
-#else
- usleep (backoff_usecs * 2 << dbi_conn->error_repeat);
-#endif
- PINFO ("DBI error: %s - Reconnecting...\n", msg);
- if (dbi_conn)
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_CANT_CONNECT, 1, TRUE);
- dbi_conn->conn_ok = TRUE;
- (void)dbi_conn_connect (conn);
- }
+ dbi_conn->set_error (ERR_BACKEND_CANT_CONNECT, 1, true);
+ dbi_conn->retry_connection (msg);
}
else // Any other error
{
PERR ("DBI error: %s\n", msg);
if (dbi_conn)
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_MISC, 0, FALSE);
+ dbi_conn->set_error (ERR_BACKEND_MISC, 0, FALSE);
}
}
@@ -1131,9 +1109,9 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
if (be->sql_be.conn != nullptr)
{
- gnc_sql_connection_dispose (be->sql_be.conn);
+ delete (be->sql_be.conn);
}
- be->sql_be.conn = create_dbi_connection (GNC_DBI_PROVIDER_MYSQL, qbe,
+ be->sql_be.conn = new GncDbiSqlConnection (GNC_DBI_PROVIDER_MYSQL, qbe,
be->conn);
}
be->sql_be.timespec_format = MYSQL_TIMESPEC_STR_FORMAT;
@@ -1226,13 +1204,9 @@ static void
pgsql_error_fn (dbi_conn conn, void* user_data)
{
GncDbiBackend* be = (GncDbiBackend*)user_data;
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)be->sql_be.conn;
+ GncDbiSqlConnection* dbi_conn =
+ dynamic_cast<decltype(dbi_conn)>(be->sql_be.conn);
const gchar* msg;
-#ifdef G_OS_WIN32
- const guint backoff_msecs = 1;
-#else
- const guint backoff_usecs = 1000;
-#endif
(void)dbi_conn_error (conn, &msg);
if (g_str_has_prefix (msg, "FATAL: database") &&
@@ -1240,7 +1214,7 @@ pgsql_error_fn (dbi_conn conn, void* user_data)
{
PINFO ("DBI error: %s\n", msg);
be->exists = FALSE;
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_NO_SUCH_DB, 0, FALSE);
+ dbi_conn->set_error (ERR_BACKEND_NO_SUCH_DB, 0, FALSE);
}
else if (g_strrstr (msg,
"server closed the connection unexpectedly")) // Connection lost
@@ -1251,38 +1225,20 @@ pgsql_error_fn (dbi_conn conn, void* user_data)
return;
}
PINFO ("DBI error: %s - Reconnecting...\n", msg);
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_CONN_LOST, 1, TRUE);
- dbi_conn->conn_ok = TRUE;
- (void)dbi_conn_connect (conn);
+ dbi_conn->set_error (ERR_BACKEND_CONN_LOST, 1, true);
+ dbi_conn->retry_connection(msg);
}
else if (dbi_conn &&
(g_str_has_prefix (msg, "connection pointer is NULL") ||
g_str_has_prefix (msg, "could not connect to server"))) // No connection
{
- if (dbi_conn->error_repeat >= DBI_MAX_CONN_ATTEMPTS)
- {
- PERR ("DBI error: %s - Giving up after %d consecutive attempts.\n", msg,
- DBI_MAX_CONN_ATTEMPTS);
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_CANT_CONNECT, 0, FALSE);
- dbi_conn->conn_ok = FALSE;
- }
- else
- {
-#ifdef G_OS_WIN32
- Sleep (backoff_msecs * 2 << dbi_conn->error_repeat);
-#else
- usleep (backoff_usecs * 2 << dbi_conn->error_repeat);
-#endif
- PINFO ("DBI error: %s - Reconnecting...\n", msg);
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_CANT_CONNECT, 1, TRUE);
- dbi_conn->conn_ok = TRUE;
- (void)dbi_conn_connect (conn);
- }
+ dbi_conn->set_error(ERR_BACKEND_CANT_CONNECT, 1, true);
+ dbi_conn->retry_connection (msg);
}
else
{
PERR ("DBI error: %s\n", msg);
- gnc_dbi_set_error (dbi_conn, ERR_BACKEND_MISC, 0, FALSE);
+ dbi_conn->set_error (ERR_BACKEND_MISC, 0, false);
}
}
@@ -1492,9 +1448,9 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
{
if (be->sql_be.conn != nullptr)
{
- gnc_sql_connection_dispose (be->sql_be.conn);
+ delete (be->sql_be.conn);
}
- be->sql_be.conn = create_dbi_connection (GNC_DBI_PROVIDER_PGSQL, qbe,
+ be->sql_be.conn = new GncDbiSqlConnection (GNC_DBI_PROVIDER_PGSQL, qbe,
be->conn);
}
be->sql_be.timespec_format = PGSQL_TIMESPEC_STR_FORMAT;
@@ -1572,7 +1528,7 @@ gnc_dbi_session_end (QofBackend* be_start)
}
if (be->sql_be.conn != nullptr)
{
- gnc_sql_connection_dispose (be->sql_be.conn);
+ delete (be->sql_be.conn);
be->sql_be.conn = nullptr;
}
gnc_sql_finalize_version_info (&be->sql_be);
@@ -1673,31 +1629,30 @@ save_may_clobber_data (QofBackend* qbe)
return retval;
}
-static dbi_result
-conn_table_manage_backup (GncDbiSqlConnection* conn,
- gchar* table_name, TableOpType op)
+dbi_result
+GncDbiSqlConnection::table_manage_backup (const std::string& table_name,
+ TableOpType op)
{
- gchar* new_name = g_strdup_printf ("%s_%s", table_name, "back");
+ auto new_name = table_name + "_back";
dbi_result result = nullptr;
switch (op)
{
case backup:
- result = dbi_conn_queryf (conn->conn, "ALTER TABLE %s RENAME TO %s",
- table_name, new_name);
+ result = dbi_conn_queryf (m_conn, "ALTER TABLE %s RENAME TO %s",
+ table_name.c_str(), new_name.c_str());
break;
case rollback:
- result = dbi_conn_queryf (conn->conn,
+ result = dbi_conn_queryf (m_conn,
"ALTER TABLE %s RENAME TO %s",
- new_name, table_name);
+ new_name.c_str(), table_name.c_str());
break;
case drop_backup:
- result = dbi_conn_queryf (conn->conn, "DROP TABLE %s",
- new_name);
+ result = dbi_conn_queryf (m_conn, "DROP TABLE %s",
+ new_name.c_str());
break;
default:
break;
}
- g_free (new_name);
return result;
}
@@ -1726,7 +1681,7 @@ conn_table_manage_backup (GncDbiSqlConnection* conn,
* @return Success (TRUE) or failure.
*/
-static gboolean
+gboolean
conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
TableOpType op)
{
@@ -1734,12 +1689,12 @@ conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
gboolean result = TRUE;
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (sql_conn);
GSList* full_table_name_list = nullptr;
- const gchar* dbname = dbi_conn_get_option (conn->conn, "dbname");
+ const gchar* dbname = dbi_conn_get_option (conn->m_conn, "dbname");
g_return_val_if_fail (table_name_list != nullptr, FALSE);
if (op == rollback)
full_table_name_list =
- conn->provider->get_table_list (conn->conn, dbname);
+ conn->m_provider->get_table_list (conn->m_conn, dbname);
for (node = table_name_list; node != nullptr && result; node = node->next)
{
@@ -1752,13 +1707,13 @@ conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
}
do
{
- gnc_dbi_init_error (conn);
+ conn->init_error ();
switch (op)
{
case rollback:
if (g_slist_find (full_table_name_list, table_name))
{
- result = dbi_conn_queryf (conn->conn, "DROP TABLE %s",
+ result = dbi_conn_queryf (conn->m_conn, "DROP TABLE %s",
table_name);
if (result)
break;
@@ -1766,20 +1721,20 @@ conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
/* Fall through */
case backup:
case drop_backup:
- result = conn_table_manage_backup (conn, table_name, op);
+ result = conn->table_manage_backup (table_name, op);
break;
case empty:
- result = dbi_conn_queryf (conn->conn, "DELETE FROM TABLE %s",
+ result = dbi_conn_queryf (conn->m_conn, "DELETE FROM TABLE %s",
table_name);
break;
case drop:
default:
- result = dbi_conn_queryf (conn->conn, "DROP TABLE %s",
+ result = dbi_conn_queryf (conn->m_conn, "DROP TABLE %s",
table_name);
break;
}
}
- while (conn->retry);
+ while (conn->m_retry);
if (result != nullptr)
{
if (dbi_result_free (result) < 0)
@@ -1802,7 +1757,7 @@ conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
* @param qbe: QofBackend for the session.
* @param book: QofBook to be saved in the database.
*/
-static void
+void
gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
@@ -1816,7 +1771,7 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
ENTER ("book=%p, primary=%p", book, be->primary_book);
dbname = dbi_conn_get_option (be->conn, "dbname");
- table_list = conn->provider->get_table_list (conn->conn, dbname);
+ table_list = conn->m_provider->get_table_list (conn->m_conn, dbname);
if (!conn_table_operation ((GncSqlConnection*)conn, table_list,
backup))
{
@@ -1827,12 +1782,12 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
gnc_table_slist_free (table_list);
return;
}
- index_list = conn->provider->get_index_list (conn->conn);
+ index_list = conn->m_provider->get_index_list (conn->m_conn);
for (iter = index_list; iter != nullptr; iter = g_slist_next (iter))
{
const char* errmsg;
- conn->provider->drop_index (conn->conn, static_cast<char*> (iter->data));
- if (DBI_ERROR_NONE != dbi_conn_error (conn->conn, &errmsg))
+ conn->m_provider->drop_index (conn->m_conn, static_cast<char*> (iter->data));
+ if (DBI_ERROR_NONE != dbi_conn_error (conn->m_conn, &errmsg))
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
gnc_table_slist_free (index_list);
@@ -2166,7 +2121,7 @@ GncDbiSqlResult::IteratorImpl::operator++()
if (error == DBI_ERROR_BADIDX || error == 0) //ran off the end of the results
return m_inst->m_sentinel;
PERR("Error %d incrementing results iterator.", error);
- qof_backend_set_error (m_inst->m_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_inst->m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
return m_inst->m_sentinel;
}
@@ -2263,12 +2218,12 @@ GncDbiSqlResult::IteratorImpl::get_time64_at_col (const char* col) const
GncDbiSqlResult::~GncDbiSqlResult()
{
int status = dbi_result_free (m_dbi_result);
-
+
if (status == 0)
return;
PERR ("Error %d in dbi_result_free() result.", dberror() );
- qof_backend_set_error (m_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
}
GncSqlRow&
@@ -2286,7 +2241,7 @@ GncDbiSqlResult::begin()
if (error != DBI_ERROR_BADIDX) //otherwise just an empty result set
{
PERR ("Error %d in dbi_result_first_row()", dberror());
- qof_backend_set_error (m_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_conn->qbe(), ERR_BACKEND_SERVER_ERR);
}
return m_sentinel;
}
@@ -2294,7 +2249,7 @@ GncDbiSqlResult::begin()
int
GncDbiSqlResult::dberror()
{
- return dbi_conn_error(m_conn->conn, nullptr);
+ return dbi_conn_error(m_conn->conn(), nullptr);
}
uint64_t
@@ -2307,14 +2262,14 @@ GncDbiSqlResult::size() const noexcept
class GncDbiSqlStatement : public GncSqlStatement
{
public:
- GncDbiSqlStatement(GncSqlConnection* conn, const std::string&& sql) :
+ GncDbiSqlStatement(const GncSqlConnection* conn, const std::string& sql) :
m_conn{conn}, m_sql {sql} {}
~GncDbiSqlStatement() {}
const char* to_sql() const override;
void add_where_cond(QofIdTypeConst, const PairVec&) override;
private:
- GncSqlConnection* m_conn;
+ const GncSqlConnection* m_conn;
std::string m_sql;
};
@@ -2335,206 +2290,169 @@ GncDbiSqlStatement::add_where_cond(QofIdTypeConst type_name,
if (colpair != *col_values.begin())
m_sql += " AND ";
m_sql += colpair.first + " = " +
- gnc_sql_connection_quote_string (m_conn, colpair.second.c_str());
+ m_conn->quote_string (colpair.second.c_str());
}
}
/* --------------------------------------------------------- */
-static void
-conn_dispose (GncSqlConnection* conn)
-{
- //GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
-
- g_free (conn);
-}
-
-static GncSqlResultPtr
-conn_execute_select_statement (GncSqlConnection* conn,
- const GncSqlStatementPtr& stmt)
+GncSqlResultPtr
+GncDbiSqlConnection::execute_select_statement (const GncSqlStatementPtr& stmt)
+ noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
dbi_result result;
DEBUG ("SQL: %s\n", stmt->to_sql());
gnc_push_locale (LC_NUMERIC, "C");
do
{
- gnc_dbi_init_error (dbi_conn);
- result = dbi_conn_query (dbi_conn->conn, stmt->to_sql());
+ init_error ();
+ result = dbi_conn_query (m_conn, stmt->to_sql());
}
- while (dbi_conn->retry);
+ while (m_retry);
if (result == nullptr)
PERR ("Error executing SQL %s\n", stmt->to_sql());
gnc_pop_locale (LC_NUMERIC);
- return GncSqlResultPtr(new GncDbiSqlResult (dbi_conn, result));
+ return GncSqlResultPtr(new GncDbiSqlResult (this, result));
}
-static gint
-conn_execute_nonselect_statement (GncSqlConnection* conn,
- const GncSqlStatementPtr& stmt)
+int
+GncDbiSqlConnection::execute_nonselect_statement (const GncSqlStatementPtr& stmt)
+ noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
dbi_result result;
- gint num_rows;
- gint status;
DEBUG ("SQL: %s\n", stmt->to_sql());
do
{
- gnc_dbi_init_error (dbi_conn);
- result = dbi_conn_query (dbi_conn->conn, stmt->to_sql());
+ init_error ();
+ result = dbi_conn_query (m_conn, stmt->to_sql());
}
- while (dbi_conn->retry);
- if (result == nullptr && dbi_conn->last_error)
+ while (m_retry);
+ if (result == nullptr && m_last_error)
{
PERR ("Error executing SQL %s\n", stmt->to_sql());
return -1;
}
- num_rows = (gint)dbi_result_get_numrows_affected (result);
- status = dbi_result_free (result);
+ if (!result)
+ return 0;
+ auto num_rows = (gint)dbi_result_get_numrows_affected (result);
+ auto status = dbi_result_free (result);
if (status < 0)
{
PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
return num_rows;
}
-static GncSqlStatementPtr
-conn_create_statement_from_sql (GncSqlConnection* conn, const gchar* sql)
+GncSqlStatementPtr
+GncDbiSqlConnection::create_statement_from_sql (const std::string& sql)
+ const noexcept
{
- return std::unique_ptr<GncSqlStatement>(new GncDbiSqlStatement (conn, sql));
+ return std::unique_ptr<GncSqlStatement>{new GncDbiSqlStatement (this, sql)};
}
-static gboolean
-conn_does_table_exist (GncSqlConnection* conn, const gchar* table_name)
+bool
+GncDbiSqlConnection::does_table_exist (const std::string& table_name)
+ const noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
- gint nTables;
- dbi_result tables;
- const gchar* dbname;
- gint status;
-
- g_return_val_if_fail (conn != nullptr, FALSE);
- g_return_val_if_fail (table_name != nullptr, FALSE);
-
- dbname = dbi_conn_get_option (dbi_conn->conn, "dbname");
- tables = dbi_conn_get_table_list (dbi_conn->conn, dbname, table_name);
- nTables = (gint)dbi_result_get_numrows (tables);
- status = dbi_result_free (tables);
+ auto dbname = dbi_conn_get_option (m_conn, "dbname");
+ auto tables = dbi_conn_get_table_list (m_conn, dbname, table_name.c_str());
+ auto nTables = dbi_result_get_numrows (tables);
+ auto status = dbi_result_free (tables);
if (status < 0)
{
PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
- if (nTables == 1)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ return nTables == 1;
}
-static gboolean
-conn_begin_transaction (GncSqlConnection* conn)
+bool
+GncDbiSqlConnection::begin_transaction () noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
dbi_result result;
- gint status;
- gboolean success = FALSE;
DEBUG ("BEGIN\n");
- if (!gnc_dbi_verify_conn (dbi_conn))
+ if (!verify ())
{
PERR ("gnc_dbi_verify_conn() failed\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
return FALSE;
}
do
{
- gnc_dbi_init_error (dbi_conn);
- result = dbi_conn_queryf (dbi_conn->conn, "BEGIN");
+ init_error ();
+ result = dbi_conn_queryf (m_conn, "BEGIN");
}
- while (dbi_conn->retry);
+ while (m_retry);
- success = (result != nullptr);
- status = dbi_result_free (result);
+ auto success = (result != nullptr);
+ auto status = dbi_result_free (result);
if (status < 0)
{
PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
if (!success)
{
PERR ("BEGIN transaction failed()\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
return success;
}
-static gboolean
-conn_rollback_transaction (GncSqlConnection* conn)
+bool
+GncDbiSqlConnection::rollback_transaction () const noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
- dbi_result result;
- gint status;
- gboolean success = FALSE;
-
DEBUG ("ROLLBACK\n");
const char* command = "ROLLBACK";
- result = dbi_conn_query (dbi_conn->conn, command);
- success = (result != nullptr);
+ auto result = dbi_conn_query (m_conn, command);
+ auto success = (result != nullptr);
- status = dbi_result_free (result);
+ auto status = dbi_result_free (result);
if (status < 0)
{
PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
if (!success)
{
PERR ("Error in conn_rollback_transaction()\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
return success;
}
-static gboolean
-conn_commit_transaction (GncSqlConnection* conn)
+bool
+GncDbiSqlConnection::commit_transaction () const noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
- dbi_result result;
- gint status;
- gboolean success = FALSE;
-
DEBUG ("COMMIT\n");
- result = dbi_conn_queryf (dbi_conn->conn, "COMMIT");
- success = (result != nullptr);
+ auto result = dbi_conn_queryf (m_conn, "COMMIT");
+ auto success = (result != nullptr);
- status = dbi_result_free (result);
+ auto status = dbi_result_free (result);
if (status < 0)
{
PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
if (!success)
{
PERR ("Error in conn_commit_transaction()\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
return success;
}
static gchar*
-create_index_ddl (GncSqlConnection* conn, const char* index_name,
+create_index_ddl (const GncSqlConnection* conn, const char* index_name,
const char* table_name, const EntryVec& col_table)
{
GString* ddl;
@@ -2558,8 +2476,8 @@ create_index_ddl (GncSqlConnection* conn, const char* index_name,
return g_string_free (ddl, FALSE);
}
-static gchar*
-add_columns_ddl(GncSqlConnection* conn,
+gchar*
+add_columns_ddl(const GncSqlConnection* conn,
const gchar* table_name,
const ColVec& info_vec)
{
@@ -2578,7 +2496,7 @@ add_columns_ddl(GncSqlConnection* conn,
(void)g_string_append (ddl, ", ");
}
g_string_append (ddl, "ADD COLUMN ");
- dbi_conn->provider->append_col_def (ddl, info);
+ dbi_conn->m_provider->append_col_def (ddl, info);
}
return g_string_free (ddl, FALSE);
@@ -2631,7 +2549,7 @@ append_sqlite3_col_def(GString* ddl, const GncSqlColumnInfo& info)
}
static gchar*
-conn_create_table_ddl_sqlite3 (GncSqlConnection* conn,
+conn_create_table_ddl_sqlite3 (const GncSqlConnection* conn,
const gchar* table_name,
const ColVec& info_vec)
{
@@ -2714,8 +2632,8 @@ append_mysql_col_def (GString* ddl, const GncSqlColumnInfo& info)
}
static gchar*
-conn_create_table_ddl_mysql (GncSqlConnection* conn, const gchar* table_name,
- const ColVec& info_vec)
+conn_create_table_ddl_mysql (const GncSqlConnection* conn,
+ const gchar* table_name, const ColVec& info_vec)
{
GString* ddl;
unsigned int col_num = 0;
@@ -2796,7 +2714,7 @@ append_pgsql_col_def (GString* ddl, const GncSqlColumnInfo& info)
}
static gchar*
-conn_create_table_ddl_pgsql (GncSqlConnection* conn, const gchar* table_name,
+conn_create_table_ddl_pgsql (const GncSqlConnection* conn, const gchar* table_name,
const ColVec& info_vec)
{
GString* ddl;
@@ -2820,129 +2738,106 @@ conn_create_table_ddl_pgsql (GncSqlConnection* conn, const gchar* table_name,
return g_string_free (ddl, FALSE);
}
-static gboolean
-conn_create_table (GncSqlConnection* conn, const gchar* table_name,
- const ColVec& info_vec)
+bool
+GncDbiSqlConnection::create_table (const std::string& table_name,
+ const ColVec& info_vec) const noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
- gchar* ddl;
- dbi_result result;
-
- g_return_val_if_fail (conn != nullptr, FALSE);
- g_return_val_if_fail (table_name != nullptr, FALSE);
-
- ddl = dbi_conn->provider->create_table_ddl(conn, table_name, info_vec);
+ auto ddl = m_provider->create_table_ddl(this, table_name.c_str(), info_vec);
if (ddl != nullptr)
{
- gint status;
DEBUG ("SQL: %s\n", ddl);
- result = dbi_conn_query (dbi_conn->conn, ddl);
+ auto result = dbi_conn_query (m_conn, ddl);
g_free (ddl);
- status = dbi_result_free (result);
+ auto status = dbi_result_free (result);
if (status < 0)
{
PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
}
else
{
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-static gboolean
-conn_create_index(GncSqlConnection* conn, const char* index_name,
- const char* table_name, const EntryVec& col_table)
+bool
+GncDbiSqlConnection::create_index(const std::string& index_name,
+ const std::string& table_name,
+ const EntryVec& col_table) const noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
- gchar* ddl;
- dbi_result result;
-
- g_return_val_if_fail (conn != nullptr, FALSE);
- g_return_val_if_fail (index_name != nullptr, FALSE);
- g_return_val_if_fail (table_name != nullptr, FALSE);
-
- ddl = create_index_ddl (conn, index_name, table_name, col_table);
+ auto ddl = create_index_ddl (this, index_name.c_str(), table_name.c_str(),
+ col_table);
if (ddl != nullptr)
{
- gint status;
-
DEBUG ("SQL: %s\n", ddl);
- result = dbi_conn_query (dbi_conn->conn, ddl);
+ auto result = dbi_conn_query (m_conn, ddl);
g_free (ddl);
- status = dbi_result_free (result);
+ auto status = dbi_result_free (result);
if (status < 0)
{
PERR ("Error in dbi_result_free() result\n");
- qof_backend_set_error (dbi_conn->qbe, ERR_BACKEND_SERVER_ERR);
+ qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
}
else
{
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-static gboolean
-conn_add_columns_to_table(GncSqlConnection* conn, const char* table_name,
- const ColVec& info_vec)
+bool
+GncDbiSqlConnection::add_columns_to_table(const std::string& table_name,
+ const ColVec& info_vec)
+ const noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
- gchar* ddl;
- dbi_result result;
-
- g_return_val_if_fail (conn != nullptr, FALSE);
- g_return_val_if_fail (table_name != nullptr, FALSE);
-
- ddl = add_columns_ddl(conn, table_name, info_vec);
+ auto ddl = add_columns_ddl(this, table_name.c_str(), info_vec);
if (ddl == nullptr)
return FALSE;
DEBUG ("SQL: %s\n", ddl);
- result = dbi_conn_query (dbi_conn->conn, ddl);
+ auto result = dbi_conn_query (m_conn, ddl);
g_free (ddl);
- int status = dbi_result_free (result);
+ auto status = dbi_result_free (result);
if (status < 0)
{
PERR( "Error in dbi_result_free() result\n" );
- qof_backend_set_error( dbi_conn->qbe, ERR_BACKEND_SERVER_ERR );
+ qof_backend_set_error(m_qbe, ERR_BACKEND_SERVER_ERR );
}
- return TRUE;
+ return true;
}
-static gchar*
-conn_quote_string (const GncSqlConnection* conn, const char* unquoted_str)
+std::string
+GncDbiSqlConnection::quote_string (const std::string& unquoted_str)
+ const noexcept
{
- GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
gchar* quoted_str;
size_t size;
- size = dbi_conn_quote_string_copy (dbi_conn->conn, unquoted_str,
+ size = dbi_conn_quote_string_copy (m_conn, unquoted_str.c_str(),
"ed_str);
if (size != 0)
{
- return quoted_str;
+ return std::string{quoted_str};
}
else
{
- return nullptr;
+ return std::string{""};
}
}
static GSList*
conn_get_table_list (dbi_conn conn, const gchar* dbname)
{
- dbi_result tables;
GSList* list = nullptr;
- tables = dbi_conn_get_table_list (conn, dbname, nullptr);
+ auto tables = dbi_conn_get_table_list (conn, dbname, nullptr);
while (dbi_result_next_row (tables) != 0)
{
const gchar* table_name;
@@ -3068,7 +2963,7 @@ conn_test_dbi_library (dbi_conn conn)
dbi_conn_error (conn, &errmsg);
PWARN ("Test_DBI_Library: Failed to retrieve test row into table: %s",
errmsg);
- result = dbi_conn_query (conn, "DROP TABLE numtest");
+ dbi_conn_query (conn, "DROP TABLE numtest");
gnc_pop_locale (LC_NUMERIC);
return GNC_DBI_FAIL_SETUP;
}
@@ -3105,35 +3000,4 @@ conn_test_dbi_library (dbi_conn conn)
}
-static GncSqlConnection*
-create_dbi_connection (provider_functions_t* provider,
- QofBackend* qbe,
- dbi_conn conn)
-{
- GncDbiSqlConnection* dbi_conn;
-
- dbi_conn = g_new0 (GncDbiSqlConnection, 1);
- g_assert (dbi_conn != nullptr);
-
- dbi_conn->base.dispose = conn_dispose;
- dbi_conn->base.executeSelectStatement = conn_execute_select_statement;
- dbi_conn->base.executeNonSelectStatement = conn_execute_nonselect_statement;
- dbi_conn->base.createStatementFromSql = conn_create_statement_from_sql;
- dbi_conn->base.doesTableExist = conn_does_table_exist;
- dbi_conn->base.beginTransaction = conn_begin_transaction;
- dbi_conn->base.rollbackTransaction = conn_rollback_transaction;
- dbi_conn->base.commitTransaction = conn_commit_transaction;
- dbi_conn->base.createTable = conn_create_table;
- dbi_conn->base.createIndex = conn_create_index;
- dbi_conn->base.addColumnsToTable = conn_add_columns_to_table;
- dbi_conn->base.quoteString = conn_quote_string;
- dbi_conn->qbe = qbe;
- dbi_conn->conn = conn;
- dbi_conn->provider = provider;
- dbi_conn->conn_ok = TRUE;
- gnc_dbi_init_error (dbi_conn);
-
- return (GncSqlConnection*)dbi_conn;
-}
-
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/dbi/test/test-backend-dbi-basic.cpp b/src/backend/dbi/test/test-backend-dbi-basic.cpp
index 03e1bd7..41c4f8c 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.cpp
+++ b/src/backend/dbi/test/test-backend-dbi-basic.cpp
@@ -359,16 +359,16 @@ test_conn_index_functions (QofBackend* qbe)
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (be->sql_be.conn);
GSList* index_list, *iter;
- index_list = conn->provider->get_index_list (be->conn);
+ index_list = conn->provider()->get_index_list (be->conn);
g_test_message ("Returned from index list\n");
g_assert (index_list != NULL);
g_assert_cmpint (g_slist_length (index_list), == , 4);
for (iter = index_list; iter != NULL; iter = g_slist_next (iter))
{
const char* errmsg;
- conn->provider->drop_index (be->conn,
+ conn->provider()->drop_index (be->conn,
static_cast<const char*> (iter->data));
- g_assert (DBI_ERROR_NONE == dbi_conn_error (conn->conn, &errmsg));
+ g_assert (DBI_ERROR_NONE == dbi_conn_error (conn->conn(), &errmsg));
}
g_slist_free (index_list);
diff --git a/src/backend/dbi/test/test-dbi-stuff.cpp b/src/backend/dbi/test/test-dbi-stuff.cpp
index 58526af..c04af87 100644
--- a/src/backend/dbi/test/test-dbi-stuff.cpp
+++ b/src/backend/dbi/test/test-dbi-stuff.cpp
@@ -218,16 +218,16 @@ test_conn_index_functions (QofBackend* qbe)
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (be->sql_be.conn);
GSList* index_list, *iter;
- index_list = conn->provider->get_index_list (be->conn);
+ index_list = conn->provider()->get_index_list (be->conn);
g_test_message ("Returned from index list\n");
g_assert (index_list != NULL);
g_assert_cmpint (g_slist_length (index_list), == , 4);
for (iter = index_list; iter != NULL; iter = g_slist_next (iter))
{
const char* errmsg;
- conn->provider->drop_index (be->conn,
+ conn->provider()->drop_index (be->conn,
static_cast<const char*> (iter->data));
- g_assert (DBI_ERROR_NONE == dbi_conn_error (conn->conn, &errmsg));
+ g_assert (DBI_ERROR_NONE == dbi_conn_error (conn->conn(), &errmsg));
}
g_slist_free (index_list);
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index 58cf98d..ba0da85 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -462,7 +462,7 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
be->obj_total += gnc_book_count_transactions (book);
be->operations_done = 0;
- is_ok = gnc_sql_connection_begin_transaction (be->conn);
+ is_ok = be->conn->begin_transaction ();
// FIXME: should write the set of commodities that are used
//write_commodities( be, book );
@@ -494,7 +494,7 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
}
if (is_ok)
{
- is_ok = gnc_sql_connection_commit_transaction (be->conn);
+ is_ok = be->conn->commit_transaction ();
}
if (is_ok)
{
@@ -509,7 +509,7 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
{
if (!qof_backend_check_error ((QofBackend*)be))
qof_backend_set_error ((QofBackend*)be, ERR_BACKEND_SERVER_ERR);
- is_ok = gnc_sql_connection_rollback_transaction (be->conn);
+ is_ok = be->conn->rollback_transaction ();
}
finish_progress (be);
LEAVE ("book=%p", book);
@@ -573,7 +573,7 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
if (qof_book_is_readonly (be->book))
{
qof_backend_set_error ((QofBackend*)be, ERR_BACKEND_READONLY);
- (void)gnc_sql_connection_rollback_transaction (be->conn);
+ (void)be->conn->rollback_transaction ();
return;
}
/* During initial load where objects are being created, don't commit
@@ -608,7 +608,7 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
return;
}
- if (!gnc_sql_connection_begin_transaction (be->conn))
+ if (!be->conn->begin_transaction ())
{
PERR ("gnc_sql_commit_edit(): begin_transaction failed\n");
LEAVE ("Rolled back - database transaction begin error");
@@ -626,7 +626,7 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
if (!be_data.is_known)
{
PERR ("gnc_sql_commit_edit(): Unknown object type '%s'\n", inst->e_type);
- (void)gnc_sql_connection_rollback_transaction (be->conn);
+ (void)be->conn->rollback_transaction ();
// Don't let unknown items still mark the book as being dirty
qof_book_mark_session_saved (be->book);
@@ -637,14 +637,14 @@ gnc_sql_commit_edit (GncSqlBackend* be, QofInstance* inst)
if (!be_data.is_ok)
{
// Error - roll it back
- (void)gnc_sql_connection_rollback_transaction (be->conn);
+ (void)be->conn->rollback_transaction ();
// This *should* leave things marked dirty
LEAVE ("Rolled back - database error");
return;
}
- (void)gnc_sql_connection_commit_transaction (be->conn);
+ (void)be->conn->commit_transaction ();
qof_book_mark_session_saved (be->book);
qof_instance_mark_clean (inst);
@@ -1869,7 +1869,7 @@ gnc_sql_execute_select_statement (GncSqlBackend* be,
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (stmt != NULL, NULL);
- auto result = gnc_sql_connection_execute_select_statement (be->conn, stmt);
+ auto result = be->conn->execute_select_statement (stmt);
if (result == NULL)
{
PERR ("SQL error: %s\n", stmt->to_sql());
@@ -1886,8 +1886,8 @@ gnc_sql_create_statement_from_sql (GncSqlBackend* be, const gchar* sql)
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (sql != NULL, NULL);
- auto stmt = gnc_sql_connection_create_statement_from_sql (be->conn, sql);
- if (stmt == NULL)
+ auto stmt = be->conn->create_statement_from_sql (sql);
+ if (stmt == nullptr)
{
PERR ("SQL error: %s\n", sql);
if (!qof_backend_check_error(&be->be))
@@ -1908,8 +1908,8 @@ gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql)
{
return nullptr;
}
- auto result = gnc_sql_connection_execute_select_statement (be->conn, stmt);
- if (result == NULL)
+ auto result = be->conn->execute_select_statement (stmt);
+ if (result == nullptr)
{
PERR ("SQL error: %s\n", sql);
if (!qof_backend_check_error(&be->be))
@@ -1930,8 +1930,7 @@ gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql)
{
return -1;
}
- auto result = gnc_sql_connection_execute_nonselect_statement (be->conn,
- stmt);
+ auto result = be->conn->execute_nonselect_statement (stmt);
return result;
}
@@ -2041,9 +2040,7 @@ gnc_sql_do_db_operation (GncSqlBackend* be,
}
if (stmt != nullptr)
{
- gint result;
-
- result = gnc_sql_connection_execute_nonselect_statement (be->conn, stmt);
+ auto result = be->conn->execute_nonselect_statement (stmt);
if (result == -1)
{
PERR ("SQL error: %s\n", stmt->to_sql());
@@ -2088,13 +2085,11 @@ build_insert_statement (GncSqlBackend* be,
{
if (col_value != *values.begin())
sql << ",";
- sql <<
- gnc_sql_connection_quote_string(be->conn, col_value.second.c_str());
+ sql << be->conn->quote_string(col_value.second);
}
sql << ")";
- stmt = gnc_sql_connection_create_statement_from_sql(be->conn,
- sql.str().c_str());
+ stmt = be->conn->create_statement_from_sql(sql.str());
return stmt;
}
@@ -2123,10 +2118,10 @@ build_update_statement (GncSqlBackend* be,
if (col_value != *values.begin())
sql << ",";
sql << col_value.first << "=" <<
- gnc_sql_connection_quote_string(be->conn, col_value.second.c_str());
+ be->conn->quote_string(col_value.second);
}
- stmt = gnc_sql_connection_create_statement_from_sql(be->conn, sql.str().c_str());
+ stmt = be->conn->create_statement_from_sql(sql.str());
/* We want our where condition to be just the first column and
* value, i.e. the guid of the object.
*/
@@ -2149,8 +2144,7 @@ build_delete_statement (GncSqlBackend* be,
g_return_val_if_fail (pObject != NULL, NULL);
sql << "DELETE FROM " << table_name;
- auto stmt = gnc_sql_connection_create_statement_from_sql (be->conn,
- sql.str().c_str());
+ auto stmt = be->conn->create_statement_from_sql (sql.str());
/* WHERE */
PairVec values;
@@ -2219,7 +2213,7 @@ do_create_table (const GncSqlBackend* be, const gchar* table_name,
{
table_row->add_to_table (be, info_vec);
}
- ok = gnc_sql_connection_create_table (be->conn, table_name, info_vec);
+ ok = be->conn->create_table (table_name, info_vec);
return ok;
}
@@ -2276,8 +2270,7 @@ gnc_sql_create_index (const GncSqlBackend* be, const gchar* index_name,
g_return_val_if_fail (index_name != NULL, FALSE);
g_return_val_if_fail (table_name != NULL, FALSE);
- ok = gnc_sql_connection_create_index (be->conn, index_name, table_name,
- col_table);
+ ok = be->conn->create_index (index_name, table_name, col_table);
return ok;
}
@@ -2342,7 +2335,7 @@ gboolean gnc_sql_add_columns_to_table (GncSqlBackend* be, const gchar* table_nam
{
table_row->add_to_table (be, info_vec);
}
- ok = gnc_sql_connection_add_columns_to_table(be->conn, table_name, info_vec);
+ ok = be->conn->add_columns_to_table(table_name, info_vec);
return ok;
}
@@ -2376,7 +2369,7 @@ gnc_sql_init_version_info (GncSqlBackend* be)
}
be->versions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- if (gnc_sql_connection_does_table_exist (be->conn, VERSION_TABLE_NAME))
+ if (be->conn->does_table_exist (VERSION_TABLE_NAME))
{
auto sql = g_strdup_printf ("SELECT * FROM %s", VERSION_TABLE_NAME);
auto result = gnc_sql_execute_select_sql (be, sql);
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 5df615b..7f145bc 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -58,7 +58,7 @@ using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
using ColVec = std::vector<GncSqlColumnInfo>;
using StrVec = std::vector<std::string>;
using PairVec = std::vector<std::pair<std::string, std::string>>;
-typedef struct GncSqlConnection GncSqlConnection;
+class GncSqlConnection;
/**
* @struct GncSqlBackend
@@ -158,49 +158,40 @@ public:
using GncSqlStatementPtr = std::unique_ptr<GncSqlStatement>;
/**
- * @struct GncSqlConnection
- *
- * Struct which represents the connection to an SQL database. SQL backends
- * must provide a structure which implements all of the functions.
+ * Encapsulate the connection to the database.
*/
-struct GncSqlConnection
+class GncSqlConnection
{
- void (*dispose) (GncSqlConnection*);
- GncSqlResultPtr (*executeSelectStatement) (GncSqlConnection*, const GncSqlStatementPtr&); /**< Returns NULL if error */
- gint (*executeNonSelectStatement) (GncSqlConnection*, const GncSqlStatementPtr&); /**< Returns -1 if error */
- GncSqlStatementPtr (*createStatementFromSql) (GncSqlConnection*, const gchar*);
- gboolean (*doesTableExist) (GncSqlConnection*, const gchar*); /**< Returns true if successful */
- gboolean (*beginTransaction) (GncSqlConnection*); /**< Returns TRUE if successful, FALSE if error */
- gboolean (*rollbackTransaction) (GncSqlConnection*); /**< Returns TRUE if successful, FALSE if error */
- gboolean (*commitTransaction) (GncSqlConnection*); /**< Returns TRUE if successful, FALSE if error */
- gboolean (*createTable) (GncSqlConnection*, const gchar*, const ColVec&); /**< Returns TRUE if successful, FALSE if error */
- gboolean (*createIndex) (GncSqlConnection*, const gchar*, const gchar*, const EntryVec&); /**< Returns TRUE if successful, FALSE if error */
- gboolean (*addColumnsToTable) (GncSqlConnection*, const gchar* table, const ColVec&); /**< Returns TRUE if successful, FALSE if error */
- gchar* (*quoteString) (const GncSqlConnection*, const char*);
+public:
+ /** Returns NULL if error */
+ virtual ~GncSqlConnection() = default;
+ virtual GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
+ noexcept = 0;
+ /** Returns false if error */
+ virtual int execute_nonselect_statement (const GncSqlStatementPtr&)
+ noexcept = 0;
+ virtual GncSqlStatementPtr create_statement_from_sql (const std::string&)
+ const noexcept = 0;
+ /** Returns true if successful */
+ virtual bool does_table_exist (const std::string&) const noexcept = 0;
+ /** Returns TRUE if successful, false if error */
+ virtual bool begin_transaction () noexcept = 0;
+ /** Returns TRUE if successful, FALSE if error */
+ virtual bool rollback_transaction () const noexcept = 0;
+ /** Returns TRUE if successful, FALSE if error */
+ virtual bool commit_transaction () const noexcept = 0;
+ /** Returns TRUE if successful, FALSE if error */
+ virtual bool create_table (const std::string&, const ColVec&)
+ const noexcept = 0;
+ /** Returns TRUE if successful, FALSE if error */
+ virtual bool create_index (const std::string&, const std::string&,
+ const EntryVec&) const noexcept = 0;
+ /** Returns TRUE if successful, FALSE if error */
+ virtual bool add_columns_to_table (const std::string&, const ColVec&)
+ const noexcept = 0;
+ virtual std::string quote_string (const std::string&)
+ const noexcept = 0;
};
-#define gnc_sql_connection_dispose(CONN) (CONN)->dispose(CONN)
-#define gnc_sql_connection_execute_select_statement(CONN,STMT) \
- (CONN)->executeSelectStatement(CONN,STMT)
-#define gnc_sql_connection_execute_nonselect_statement(CONN,STMT) \
- (CONN)->executeNonSelectStatement(CONN,STMT)
-#define gnc_sql_connection_create_statement_from_sql(CONN,SQL) \
- (CONN)->createStatementFromSql(CONN,SQL)
-#define gnc_sql_connection_does_table_exist(CONN,NAME) \
- (CONN)->doesTableExist(CONN,NAME)
-#define gnc_sql_connection_begin_transaction(CONN) \
- (CONN)->beginTransaction(CONN)
-#define gnc_sql_connection_rollback_transaction(CONN) \
- (CONN)->rollbackTransaction(CONN)
-#define gnc_sql_connection_commit_transaction(CONN) \
- (CONN)->commitTransaction(CONN)
-#define gnc_sql_connection_create_table(CONN,NAME,COLLIST) \
- (CONN)->createTable(CONN,NAME,COLLIST)
-#define gnc_sql_connection_create_index(CONN,INDEXNAME,TABLENAME,COLTABLE) \
- (CONN)->createIndex(CONN,INDEXNAME,TABLENAME,COLTABLE)
-#define gnc_sql_connection_add_columns_to_table(CONN,TABLENAME,COLLIST) \
- (CONN)->addColumnsToTable(CONN,TABLENAME,COLLIST)
-#define gnc_sql_connection_quote_string(CONN,STR) \
- (CONN)->quoteString(CONN,STR)
/**
* Struct used to represent a row in the result of an SQL SELECT statement.
diff --git a/src/backend/sql/gnc-bill-term-sql.cpp b/src/backend/sql/gnc-bill-term-sql.cpp
index 3f61d9b..28cb6b2 100644
--- a/src/backend/sql/gnc-bill-term-sql.cpp
+++ b/src/backend/sql/gnc-bill-term-sql.cpp
@@ -284,31 +284,20 @@ GncSqlBillTermBackend::load_all (GncSqlBackend* be)
}
/* ================================================================= */
-typedef struct
-{
- GncSqlBackend* be;
- GncSqlBillTermBackend* btbe;
- bool is_ok;
-} write_billterms_t;
static void
-do_save_billterm (QofInstance* inst, gpointer p2)
+do_save_billterm (QofInstance* inst, void* p2)
{
- write_billterms_t* data = (write_billterms_t*)p2;
-
- if (data->is_ok)
- {
- data->is_ok = data->btbe->commit (data->be, inst);
- }
+ auto data = static_cast<write_objects_t*>(p2);
+ data->commit(inst);
}
bool
GncSqlBillTermBackend::write (GncSqlBackend* be)
{
- write_billterms_t data {be, this, true};
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data {be, true, this};
qof_object_foreach (GNC_ID_BILLTERM, be->book, do_save_billterm, &data);
return data.is_ok;
}
diff --git a/src/backend/sql/gnc-customer-sql.cpp b/src/backend/sql/gnc-customer-sql.cpp
index ce923fd..43bce7f 100644
--- a/src/backend/sql/gnc-customer-sql.cpp
+++ b/src/backend/sql/gnc-customer-sql.cpp
@@ -198,9 +198,9 @@ write_single_customer (QofInstance* term_p, gpointer data_p)
g_return_if_fail (GNC_IS_CUSTOMER (term_p));
g_return_if_fail (data_p != NULL);
- if (customer_should_be_saved (GNC_CUSTOMER (term_p)) && data->is_ok)
+ if (customer_should_be_saved (GNC_CUSTOMER (term_p)))
{
- data->is_ok = data->obe->commit (data->be, term_p);
+ data->commit (term_p);
}
}
diff --git a/src/backend/sql/gnc-recurrence-sql.cpp b/src/backend/sql/gnc-recurrence-sql.cpp
index 112bcab..10d1a81 100644
--- a/src/backend/sql/gnc-recurrence-sql.cpp
+++ b/src/backend/sql/gnc-recurrence-sql.cpp
@@ -321,7 +321,7 @@ gnc_sql_set_recurrences_from_db (GncSqlBackend* be, const GncGUID* guid)
(void)guid_to_string_buff (guid, guid_buf);
buf = g_strdup_printf ("SELECT * FROM %s WHERE obj_guid='%s'", TABLE_NAME,
guid_buf);
- auto stmt = gnc_sql_connection_create_statement_from_sql (be->conn, buf);
+ auto stmt = be->conn->create_statement_from_sql (buf);
g_free (buf);
auto result = gnc_sql_execute_select_statement (be, stmt);
return result;
diff --git a/src/backend/sql/gnc-tax-table-sql.cpp b/src/backend/sql/gnc-tax-table-sql.cpp
index ca22a60..415f766 100644
--- a/src/backend/sql/gnc-tax-table-sql.cpp
+++ b/src/backend/sql/gnc-tax-table-sql.cpp
@@ -237,7 +237,7 @@ load_taxtable_entries (GncSqlBackend* be, GncTaxTable* tt)
g_value_set_string (&value, guid_buf);
buf = g_strdup_printf ("SELECT * FROM %s WHERE taxtable='%s'",
TTENTRIES_TABLE_NAME, guid_buf);
- auto stmt = gnc_sql_connection_create_statement_from_sql (be->conn, buf);
+ auto stmt = be->conn->create_statement_from_sql (buf);
g_free (buf);
auto result = gnc_sql_execute_select_statement (be, stmt);
for (auto row : *result)
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp
index 699119f..fbbe460 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.cpp
+++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp
@@ -32,6 +32,81 @@ extern "C"
static const gchar* suitename = "/backend/sql/gnc-backend-sql";
void test_suite_gnc_backend_sql (void);
+class GncMockSqlConnection;
+
+class GncMockSqlResult : public GncSqlResult
+{
+public:
+ GncMockSqlResult(const GncMockSqlConnection* conn) :
+ m_conn{conn}, m_iter{this}, m_row{&m_iter} {}
+ uint64_t size() const noexcept { return 1; }
+ GncSqlRow& begin() { return m_row; }
+ GncSqlRow& end() { return m_row; }
+protected:
+ class IteratorImpl : public GncSqlResult::IteratorImpl
+ {
+ public:
+ ~IteratorImpl() = default;
+ IteratorImpl(GncMockSqlResult* inst) : m_inst{inst} {}
+ virtual GncSqlRow& operator++() { return m_inst->m_row; }
+ virtual GncSqlRow& operator++(int) { return ++(*this); };
+ virtual GncSqlResult* operator*() { return m_inst; }
+ virtual int64_t get_int_at_col (const char* col) const
+ { return 1LL; }
+ virtual float get_float_at_col (const char* col) const
+ { return 1.0; }
+ virtual double get_double_at_col (const char* col) const
+ { return 1.0; }
+ virtual std::string get_string_at_col (const char* col)const
+ { return std::string{"foo"}; }
+ virtual time64 get_time64_at_col (const char* col) const
+ { return 1466270857LL; }
+ virtual bool is_col_null(const char* col) const noexcept
+ { return false; }
+ private:
+ GncMockSqlResult* m_inst;
+ };
+private:
+ const GncMockSqlConnection* m_conn;
+ IteratorImpl m_iter;
+ GncSqlRow m_row;
+};
+
+class GncMockSqlStatement : public GncSqlStatement
+{
+public:
+ const char* to_sql() const { return "SELECT * FROM foo"; }
+ void add_where_cond (QofIdTypeConst, const PairVec&) {}
+};
+
+
+class GncMockSqlConnection : public GncSqlConnection
+{
+public:
+ GncMockSqlConnection() : m_result{this} {}
+ GncSqlResultPtr execute_select_statement (const GncSqlStatementPtr&)
+ noexcept override { return &m_result; }
+ int execute_nonselect_statement (const GncSqlStatementPtr&)
+ noexcept override { return 1; }
+ GncSqlStatementPtr create_statement_from_sql (const std::string&)
+ const noexcept override {
+ return std::unique_ptr<GncMockSqlStatement>(new GncMockSqlStatement); }
+ bool does_table_exist (const std::string&) const noexcept override {
+ return true; }
+ bool begin_transaction () noexcept override { return true;}
+ bool rollback_transaction () const noexcept override { return true; }
+ bool commit_transaction () const noexcept override { return true; }
+ bool create_table (const std::string&, const ColVec&)
+ const noexcept override { return false; }
+ bool create_index (const std::string&, const std::string&,
+ const EntryVec&) const noexcept override { return false; }
+ bool add_columns_to_table (const std::string&, const ColVec&)
+ const noexcept override { return false; }
+ virtual std::string quote_string (const std::string& str)
+ const noexcept override { return std::string{str}; }
+private:
+ GncMockSqlResult m_result;
+};
/* gnc_sql_init
void
@@ -185,19 +260,13 @@ test_dirty_cb (QofBook* book, gboolean dirty, gpointer data)
--* (guint*)data;
}
-static gboolean
-fake_connection_function (GncSqlConnection* conn)
-{
- return TRUE;
-}
-
static void
test_gnc_sql_commit_edit (void)
{
GncSqlBackend be;
QofInstance* inst;
guint dirty_called = 0;
- GncSqlConnection conn;
+ GncMockSqlConnection conn;
const char* msg1 =
"[gnc_sql_commit_edit()] gnc_sql_commit_edit(): Unknown object type 'null'\n";
const char* msg2 =
@@ -222,9 +291,6 @@ test_gnc_sql_commit_edit (void)
qof_object_initialize ();
be.book = qof_book_new ();
be.conn = &conn;
- conn.beginTransaction = fake_connection_function;
- conn.rollbackTransaction = fake_connection_function;
- conn.commitTransaction = fake_connection_function;
inst = static_cast<decltype (inst)> (g_object_new (QOF_TYPE_INSTANCE, NULL));
qof_instance_init_data (inst, QOF_ID_NULL, be.book);
be.loading = FALSE;
commit 12e763884e3044483c9d0a008ccf1870c7d5ae40
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Jun 18 12:38:11 2016 -0700
Use a std::unique_ptr for GncSqlStatement for better memory management.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index a7c7e72..e1c82f9 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -2349,7 +2349,8 @@ conn_dispose (GncSqlConnection* conn)
}
static GncSqlResultPtr
-conn_execute_select_statement (GncSqlConnection* conn, GncSqlStatement* stmt)
+conn_execute_select_statement (GncSqlConnection* conn,
+ const GncSqlStatementPtr& stmt)
{
GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
dbi_result result;
@@ -2370,7 +2371,7 @@ conn_execute_select_statement (GncSqlConnection* conn, GncSqlStatement* stmt)
static gint
conn_execute_nonselect_statement (GncSqlConnection* conn,
- GncSqlStatement* stmt)
+ const GncSqlStatementPtr& stmt)
{
GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
dbi_result result;
@@ -2399,10 +2400,10 @@ conn_execute_nonselect_statement (GncSqlConnection* conn,
return num_rows;
}
-static GncSqlStatement*
+static GncSqlStatementPtr
conn_create_statement_from_sql (GncSqlConnection* conn, const gchar* sql)
{
- return new GncDbiSqlStatement (conn, sql);
+ return std::unique_ptr<GncSqlStatement>(new GncDbiSqlStatement (conn, sql));
}
static gboolean
diff --git a/src/backend/sql/gnc-account-sql.cpp b/src/backend/sql/gnc-account-sql.cpp
index bdb3bff..f0114ff 100644
--- a/src/backend/sql/gnc-account-sql.cpp
+++ b/src/backend/sql/gnc-account-sql.cpp
@@ -213,7 +213,6 @@ load_single_account (GncSqlBackend* be, GncSqlRow& row,
void
GncSqlAccountBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt = NULL;
QofBook* pBook;
GList* l_accounts_needing_parents = NULL;
GSList* bal_slist;
@@ -225,14 +224,13 @@ GncSqlAccountBackend::load_all (GncSqlBackend* be)
pBook = be->book;
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- if (stmt == NULL)
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ if (stmt == nullptr)
{
LEAVE ("stmt == NULL");
return;
}
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
for (auto row : *result)
load_single_account (be, row, &l_accounts_needing_parents);
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index b4b3042..58cf98d 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -86,18 +86,21 @@ static void gnc_sql_init_object_handlers (void);
static void update_progress (GncSqlBackend* be);
static void finish_progress (GncSqlBackend* be);
static gboolean reset_version_info (GncSqlBackend* be);
-static GncSqlStatement* build_insert_statement (GncSqlBackend* be,
- const gchar* table_name,
- QofIdTypeConst obj_name, gpointer pObject,
- const EntryVec& table);
-static GncSqlStatement* build_update_statement (GncSqlBackend* be,
- const gchar* table_name,
- QofIdTypeConst obj_name, gpointer pObject,
- const EntryVec& table);
-static GncSqlStatement* build_delete_statement (GncSqlBackend* be,
- const gchar* table_name,
- QofIdTypeConst obj_name, gpointer pObject,
- const EntryVec& table);
+static GncSqlStatementPtr build_insert_statement (GncSqlBackend* be,
+ const gchar* table_name,
+ QofIdTypeConst obj_name,
+ gpointer pObject,
+ const EntryVec& table);
+static GncSqlStatementPtr build_update_statement (GncSqlBackend* be,
+ const gchar* table_name,
+ QofIdTypeConst obj_name,
+ gpointer pObject,
+ const EntryVec& table);
+static GncSqlStatementPtr build_delete_statement (GncSqlBackend* be,
+ const gchar* table_name,
+ QofIdTypeConst obj_name,
+ gpointer pObject,
+ const EntryVec& table);
static GList* post_load_commodities = NULL;
@@ -1832,22 +1835,19 @@ gnc_sql_load_object (const GncSqlBackend* be, GncSqlRow& row,
}
/* ================================================================= */
-GncSqlStatement*
+GncSqlStatementPtr
gnc_sql_create_select_statement (GncSqlBackend* be, const gchar* table_name)
{
- gchar* sql;
- GncSqlStatement* stmt;
-
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (table_name != NULL, NULL);
- sql = g_strdup_printf ("SELECT * FROM %s", table_name);
- stmt = gnc_sql_create_statement_from_sql (be, sql);
+ auto sql = g_strdup_printf ("SELECT * FROM %s", table_name);
+ auto stmt = gnc_sql_create_statement_from_sql (be, sql);
g_free (sql);
return stmt;
}
-static GncSqlStatement*
+static GncSqlStatementPtr
create_single_col_select_statement (GncSqlBackend* be,
const gchar* table_name,
const GncSqlColumnTableEntryPtr table_row)
@@ -1862,7 +1862,8 @@ create_single_col_select_statement (GncSqlBackend* be,
/* ================================================================= */
GncSqlResultPtr
-gnc_sql_execute_select_statement (GncSqlBackend* be, GncSqlStatement* stmt)
+gnc_sql_execute_select_statement (GncSqlBackend* be,
+ const GncSqlStatementPtr& stmt)
{
g_return_val_if_fail (be != NULL, NULL);
@@ -1879,15 +1880,13 @@ gnc_sql_execute_select_statement (GncSqlBackend* be, GncSqlStatement* stmt)
return result;
}
-GncSqlStatement*
+GncSqlStatementPtr
gnc_sql_create_statement_from_sql (GncSqlBackend* be, const gchar* sql)
{
- GncSqlStatement* stmt;
-
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (sql != NULL, NULL);
- stmt = gnc_sql_connection_create_statement_from_sql (be->conn, sql);
+ auto stmt = gnc_sql_connection_create_statement_from_sql (be->conn, sql);
if (stmt == NULL)
{
PERR ("SQL error: %s\n", sql);
@@ -1901,18 +1900,15 @@ gnc_sql_create_statement_from_sql (GncSqlBackend* be, const gchar* sql)
GncSqlResultPtr
gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql)
{
- GncSqlStatement* stmt;
-
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (sql != NULL, NULL);
- stmt = gnc_sql_create_statement_from_sql (be, sql);
- if (stmt == NULL)
+ auto stmt = gnc_sql_create_statement_from_sql (be, sql);
+ if (stmt == nullptr)
{
- return NULL;
+ return nullptr;
}
auto result = gnc_sql_connection_execute_select_statement (be->conn, stmt);
- delete stmt;
if (result == NULL)
{
PERR ("SQL error: %s\n", sql);
@@ -1926,19 +1922,16 @@ gnc_sql_execute_select_sql (GncSqlBackend* be, const gchar* sql)
gint
gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql)
{
- GncSqlStatement* stmt;
- gint result;
-
g_return_val_if_fail (be != NULL, 0);
g_return_val_if_fail (sql != NULL, 0);
- stmt = gnc_sql_create_statement_from_sql (be, sql);
+ auto stmt = gnc_sql_create_statement_from_sql (be, sql);
if (stmt == NULL)
{
return -1;
}
- result = gnc_sql_connection_execute_nonselect_statement (be->conn, stmt);
- delete stmt;
+ auto result = gnc_sql_connection_execute_nonselect_statement (be->conn,
+ stmt);
return result;
}
@@ -1987,7 +1980,6 @@ get_object_values (GncSqlBackend* be, QofIdTypeConst obj_name,
return vec;
}
-
gboolean
gnc_sql_object_is_it_in_db (GncSqlBackend* be, const gchar* table_name,
QofIdTypeConst obj_name, gpointer pObject,
@@ -2007,7 +1999,6 @@ gnc_sql_object_is_it_in_db (GncSqlBackend* be, const gchar* table_name,
PairVec values{get_object_values(be, obj_name, pObject, table)};
stmt->add_where_cond(obj_name, values);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
if (result != NULL)
{
auto retval = result->size() > 0;
@@ -2024,7 +2015,7 @@ gnc_sql_do_db_operation (GncSqlBackend* be,
QofIdTypeConst obj_name, gpointer pObject,
const EntryVec& table)
{
- GncSqlStatement* stmt = NULL;
+ GncSqlStatementPtr stmt;
gboolean ok = FALSE;
g_return_val_if_fail (be != NULL, FALSE);
@@ -2048,7 +2039,7 @@ gnc_sql_do_db_operation (GncSqlBackend* be,
{
g_assert (FALSE);
}
- if (stmt != NULL)
+ if (stmt != nullptr)
{
gint result;
@@ -2063,19 +2054,18 @@ gnc_sql_do_db_operation (GncSqlBackend* be,
{
ok = TRUE;
}
- delete stmt;
}
return ok;
}
-static GncSqlStatement*
+static GncSqlStatementPtr
build_insert_statement (GncSqlBackend* be,
const gchar* table_name,
QofIdTypeConst obj_name, gpointer pObject,
const EntryVec& table)
{
- GncSqlStatement* stmt;
+ GncSqlStatementPtr stmt;
PairVec col_values;
std::ostringstream sql;
@@ -2108,13 +2098,13 @@ build_insert_statement (GncSqlBackend* be,
return stmt;
}
-static GncSqlStatement*
+static GncSqlStatementPtr
build_update_statement (GncSqlBackend* be,
const gchar* table_name,
QofIdTypeConst obj_name, gpointer pObject,
const EntryVec& table)
{
- GncSqlStatement* stmt;
+ GncSqlStatementPtr stmt;
std::ostringstream sql;
g_return_val_if_fail (be != NULL, NULL);
@@ -2145,13 +2135,12 @@ build_update_statement (GncSqlBackend* be,
return stmt;
}
-static GncSqlStatement*
+static GncSqlStatementPtr
build_delete_statement (GncSqlBackend* be,
const gchar* table_name,
QofIdTypeConst obj_name, gpointer pObject,
const EntryVec& table)
{
- GncSqlStatement* stmt;
std::ostringstream sql;
g_return_val_if_fail (be != NULL, NULL);
@@ -2160,8 +2149,8 @@ build_delete_statement (GncSqlBackend* be,
g_return_val_if_fail (pObject != NULL, NULL);
sql << "DELETE FROM " << table_name;
- stmt = gnc_sql_connection_create_statement_from_sql (be->conn,
- sql.str().c_str());
+ auto stmt = gnc_sql_connection_create_statement_from_sql (be->conn,
+ sql.str().c_str());
/* WHERE */
PairVec values;
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 78fc339..5df615b 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -155,6 +155,8 @@ public:
virtual void add_where_cond (QofIdTypeConst, const PairVec&) = 0;
};
+using GncSqlStatementPtr = std::unique_ptr<GncSqlStatement>;
+
/**
* @struct GncSqlConnection
*
@@ -164,9 +166,9 @@ public:
struct GncSqlConnection
{
void (*dispose) (GncSqlConnection*);
- GncSqlResultPtr (*executeSelectStatement) (GncSqlConnection*, GncSqlStatement*); /**< Returns NULL if error */
- gint (*executeNonSelectStatement) (GncSqlConnection*, GncSqlStatement*); /**< Returns -1 if error */
- GncSqlStatement* (*createStatementFromSql) (GncSqlConnection*, const gchar*);
+ GncSqlResultPtr (*executeSelectStatement) (GncSqlConnection*, const GncSqlStatementPtr&); /**< Returns NULL if error */
+ gint (*executeNonSelectStatement) (GncSqlConnection*, const GncSqlStatementPtr&); /**< Returns -1 if error */
+ GncSqlStatementPtr (*createStatementFromSql) (GncSqlConnection*, const gchar*);
gboolean (*doesTableExist) (GncSqlConnection*, const gchar*); /**< Returns true if successful */
gboolean (*beginTransaction) (GncSqlConnection*); /**< Returns TRUE if successful, FALSE if error */
gboolean (*rollbackTransaction) (GncSqlConnection*); /**< Returns TRUE if successful, FALSE if error */
@@ -763,7 +765,7 @@ gboolean gnc_sql_do_db_operation (GncSqlBackend* be,
* @return Results, or NULL if an error has occured
*/
GncSqlResultPtr gnc_sql_execute_select_statement (GncSqlBackend* be,
- GncSqlStatement* statement);
+ const GncSqlStatementPtr& statement);
/**
* Executes an SQL SELECT statement from an SQL char string and returns the
@@ -792,8 +794,8 @@ gint gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql);
* @param sql SQL char string
* @return Statement
*/
-GncSqlStatement* gnc_sql_create_statement_from_sql (GncSqlBackend* be,
- const gchar* sql);
+GncSqlStatementPtr gnc_sql_create_statement_from_sql (GncSqlBackend* be,
+ const gchar* sql);
/**
* Loads a Gnucash object from the database.
@@ -906,8 +908,8 @@ const GncGUID* gnc_sql_load_tx_guid (const GncSqlBackend* be, GncSqlRow& row);
* @param table_name Table name
* @return Statement
*/
-GncSqlStatement* gnc_sql_create_select_statement (GncSqlBackend* be,
- const gchar* table_name);
+GncSqlStatementPtr gnc_sql_create_select_statement (GncSqlBackend* be,
+ const gchar* table_name);
/**
* Appends the ascii strings for a list of GUIDs to the end of an SQL string.
diff --git a/src/backend/sql/gnc-bill-term-sql.cpp b/src/backend/sql/gnc-bill-term-sql.cpp
index af06bd2..3f61d9b 100644
--- a/src/backend/sql/gnc-bill-term-sql.cpp
+++ b/src/backend/sql/gnc-bill-term-sql.cpp
@@ -235,13 +235,11 @@ load_single_billterm (GncSqlBackend* be, GncSqlRow& row,
void
GncSqlBillTermBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* list = NULL;
GList* l_billterms_needing_parents = NULL;
diff --git a/src/backend/sql/gnc-book-sql.cpp b/src/backend/sql/gnc-book-sql.cpp
index 2145172..081a744 100644
--- a/src/backend/sql/gnc-book-sql.cpp
+++ b/src/backend/sql/gnc-book-sql.cpp
@@ -169,15 +169,12 @@ load_single_book (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlBookBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
-
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, BOOK_TABLE);
- if (stmt != NULL)
+ auto stmt = gnc_sql_create_select_statement (be, BOOK_TABLE);
+ if (stmt != nullptr)
{
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
auto row = result->begin();
/* If there are no rows, try committing the book; unset
diff --git a/src/backend/sql/gnc-budget-sql.cpp b/src/backend/sql/gnc-budget-sql.cpp
index beb87c2..8c76172 100644
--- a/src/backend/sql/gnc-budget-sql.cpp
+++ b/src/backend/sql/gnc-budget-sql.cpp
@@ -206,22 +206,19 @@ static void
load_budget_amounts (GncSqlBackend* be, GncBudget* budget)
{
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
- gchar* sql;
- GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
g_return_if_fail (budget != NULL);
(void)guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (budget)),
guid_buf);
- sql = g_strdup_printf ("SELECT * FROM %s WHERE budget_guid='%s'",
- AMOUNTS_TABLE, guid_buf);
- stmt = gnc_sql_create_statement_from_sql (be, sql);
+ auto sql = g_strdup_printf ("SELECT * FROM %s WHERE budget_guid='%s'",
+ AMOUNTS_TABLE, guid_buf);
+ auto stmt = gnc_sql_create_statement_from_sql (be, sql);
g_free (sql);
- if (stmt != NULL)
+ if (stmt != nullptr)
{
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
budget_amount_info_t info = { budget, NULL, 0 };
for (auto row : *result)
@@ -335,16 +332,14 @@ load_single_budget (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlBudgetBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
GList* list = NULL;
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, BUDGET_TABLE);
- if (stmt != NULL)
+ auto stmt = gnc_sql_create_select_statement (be, BUDGET_TABLE);
+ if (stmt != nullptr)
{
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
for (auto row : *result)
{
auto b = load_single_budget (be, row);
diff --git a/src/backend/sql/gnc-commodity-sql.cpp b/src/backend/sql/gnc-commodity-sql.cpp
index a77090d..efac9ac 100644
--- a/src/backend/sql/gnc-commodity-sql.cpp
+++ b/src/backend/sql/gnc-commodity-sql.cpp
@@ -143,14 +143,12 @@ load_single_commodity (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlCommodityBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
gnc_commodity_table* pTable;
pTable = gnc_commodity_table_get_table (be->book);
- stmt = gnc_sql_create_select_statement (be, COMMODITIES_TABLE);
- if (stmt == NULL) return;
+ auto stmt = gnc_sql_create_select_statement (be, COMMODITIES_TABLE);
+ if (stmt == nullptr) return;
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
for (auto row : *result)
{
diff --git a/src/backend/sql/gnc-customer-sql.cpp b/src/backend/sql/gnc-customer-sql.cpp
index c8b8c6a..ce923fd 100644
--- a/src/backend/sql/gnc-customer-sql.cpp
+++ b/src/backend/sql/gnc-customer-sql.cpp
@@ -124,14 +124,11 @@ load_single_customer (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlCustomerBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
-
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* list = NULL;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-employee-sql.cpp b/src/backend/sql/gnc-employee-sql.cpp
index b66ba07..166596a 100644
--- a/src/backend/sql/gnc-employee-sql.cpp
+++ b/src/backend/sql/gnc-employee-sql.cpp
@@ -110,13 +110,10 @@ load_single_employee (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlEmployeeBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
-
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* list = NULL;
diff --git a/src/backend/sql/gnc-entry-sql.cpp b/src/backend/sql/gnc-entry-sql.cpp
index 75195df..c9ca9c1 100644
--- a/src/backend/sql/gnc-entry-sql.cpp
+++ b/src/backend/sql/gnc-entry-sql.cpp
@@ -192,13 +192,10 @@ load_single_entry (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlEntryBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
-
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* list = NULL;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-invoice-sql.cpp b/src/backend/sql/gnc-invoice-sql.cpp
index 71eb593..e3e5b03 100644
--- a/src/backend/sql/gnc-invoice-sql.cpp
+++ b/src/backend/sql/gnc-invoice-sql.cpp
@@ -131,13 +131,10 @@ load_single_invoice (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlInvoiceBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
-
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* list = NULL;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-job-sql.cpp b/src/backend/sql/gnc-job-sql.cpp
index e7992e4..da052c4 100644
--- a/src/backend/sql/gnc-job-sql.cpp
+++ b/src/backend/sql/gnc-job-sql.cpp
@@ -103,12 +103,10 @@ load_single_job (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlJobBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* list = NULL;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-lots-sql.cpp b/src/backend/sql/gnc-lots-sql.cpp
index 5693459..4e3bebe 100644
--- a/src/backend/sql/gnc-lots-sql.cpp
+++ b/src/backend/sql/gnc-lots-sql.cpp
@@ -125,14 +125,12 @@ load_single_lot (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlLotsBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- if (stmt != NULL)
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ if (stmt != nullptr)
{
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
if (result->begin () == nullptr)
return;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-order-sql.cpp b/src/backend/sql/gnc-order-sql.cpp
index 57f6954..f330f3e 100644
--- a/src/backend/sql/gnc-order-sql.cpp
+++ b/src/backend/sql/gnc-order-sql.cpp
@@ -103,12 +103,10 @@ load_single_order (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlOrderBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* list = NULL;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-price-sql.cpp b/src/backend/sql/gnc-price-sql.cpp
index f3c2f4e..1fa67b8 100644
--- a/src/backend/sql/gnc-price-sql.cpp
+++ b/src/backend/sql/gnc-price-sql.cpp
@@ -101,7 +101,6 @@ load_single_price (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlPriceBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
QofBook* pBook;
GNCPriceDB* pPriceDB;
@@ -109,11 +108,10 @@ GncSqlPriceBackend::load_all (GncSqlBackend* be)
pBook = be->book;
pPriceDB = gnc_pricedb_get_db (pBook);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
- if (stmt != NULL)
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ if (stmt != nullptr)
{
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
if (result->begin() == result->end())
return;
diff --git a/src/backend/sql/gnc-recurrence-sql.cpp b/src/backend/sql/gnc-recurrence-sql.cpp
index 44a1675..112bcab 100644
--- a/src/backend/sql/gnc-recurrence-sql.cpp
+++ b/src/backend/sql/gnc-recurrence-sql.cpp
@@ -314,7 +314,6 @@ gnc_sql_set_recurrences_from_db (GncSqlBackend* be, const GncGUID* guid)
{
gchar* buf;
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
- GncSqlStatement* stmt;
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (guid != NULL, NULL);
@@ -322,10 +321,9 @@ gnc_sql_set_recurrences_from_db (GncSqlBackend* be, const GncGUID* guid)
(void)guid_to_string_buff (guid, guid_buf);
buf = g_strdup_printf ("SELECT * FROM %s WHERE obj_guid='%s'", TABLE_NAME,
guid_buf);
- stmt = gnc_sql_connection_create_statement_from_sql (be->conn, buf);
+ auto stmt = gnc_sql_connection_create_statement_from_sql (be->conn, buf);
g_free (buf);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
return result;
}
diff --git a/src/backend/sql/gnc-schedxaction-sql.cpp b/src/backend/sql/gnc-schedxaction-sql.cpp
index 857507a..2ed4002 100644
--- a/src/backend/sql/gnc-schedxaction-sql.cpp
+++ b/src/backend/sql/gnc-schedxaction-sql.cpp
@@ -121,14 +121,11 @@ load_single_sx (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt = NULL;
-
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, SCHEDXACTION_TABLE);
+ auto stmt = gnc_sql_create_select_statement (be, SCHEDXACTION_TABLE);
if (stmt == NULL) return;
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
SchedXactions* sxes;
GList* list = NULL;
sxes = gnc_book_get_schedxactions (be->book);
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index 2a682a9..b87dfd6 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -732,7 +732,6 @@ gnc_sql_slots_delete (GncSqlBackend* be, const GncGUID* guid)
{
gchar* buf;
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
- GncSqlStatement* stmt;
slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KvpValue::Type::INVALID, NULL, FRAME, NULL, g_string_new (NULL) };
g_return_val_if_fail (be != NULL, FALSE);
@@ -742,12 +741,11 @@ gnc_sql_slots_delete (GncSqlBackend* be, const GncGUID* guid)
buf = g_strdup_printf ("SELECT * FROM %s WHERE obj_guid='%s' and slot_type in ('%d', '%d') and not guid_val is null",
TABLE_NAME, guid_buf, KvpValue::Type::FRAME, KvpValue::Type::GLIST);
- stmt = gnc_sql_create_statement_from_sql (be, buf);
+ auto stmt = gnc_sql_create_statement_from_sql (be, buf);
g_free (buf);
- if (stmt != NULL)
+ if (stmt != nullptr)
{
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
for (auto row : *result)
{
try
@@ -828,7 +826,6 @@ slots_load_info (slot_info_t* pInfo)
{
gchar* buf;
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
- GncSqlStatement* stmt;
g_return_if_fail (pInfo != NULL);
g_return_if_fail (pInfo->be != NULL);
@@ -839,12 +836,11 @@ slots_load_info (slot_info_t* pInfo)
buf = g_strdup_printf ("SELECT * FROM %s WHERE obj_guid='%s'",
TABLE_NAME, guid_buf);
- stmt = gnc_sql_create_statement_from_sql (pInfo->be, buf);
+ auto stmt = gnc_sql_create_statement_from_sql (pInfo->be, buf);
g_free (buf);
- if (stmt != NULL)
+ if (stmt != nullptr)
{
auto result = gnc_sql_execute_select_statement (pInfo->be, stmt);
- delete stmt;
for (auto row : *result)
load_slot (pInfo, row);
}
@@ -893,7 +889,6 @@ void
gnc_sql_slots_load_for_list (GncSqlBackend* be, GList* list)
{
QofCollection* coll;
- GncSqlStatement* stmt;
GString* sql;
gboolean single_item;
@@ -926,8 +921,8 @@ gnc_sql_slots_load_for_list (GncSqlBackend* be, GList* list)
}
// Execute the query and load the slots
- stmt = gnc_sql_create_statement_from_sql (be, sql->str);
- if (stmt == NULL)
+ auto stmt = gnc_sql_create_statement_from_sql (be, sql->str);
+ if (stmt == nullptr)
{
PERR ("stmt == NULL, SQL = '%s'\n", sql->str);
(void)g_string_free (sql, TRUE);
@@ -935,7 +930,6 @@ gnc_sql_slots_load_for_list (GncSqlBackend* be, GList* list)
}
(void)g_string_free (sql, TRUE);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
for (auto row : *result)
load_slot_for_list_item (be, row, coll);
}
@@ -982,7 +976,6 @@ void gnc_sql_slots_load_for_sql_subquery (GncSqlBackend* be,
BookLookupFn lookup_fn)
{
gchar* sql;
- GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
@@ -994,8 +987,8 @@ void gnc_sql_slots_load_for_sql_subquery (GncSqlBackend* be,
subquery);
// Execute the query and load the slots
- stmt = gnc_sql_create_statement_from_sql (be, sql);
- if (stmt == NULL)
+ auto stmt = gnc_sql_create_statement_from_sql (be, sql);
+ if (stmt == nullptr)
{
PERR ("stmt == NULL, SQL = '%s'\n", sql);
g_free (sql);
@@ -1003,7 +996,6 @@ void gnc_sql_slots_load_for_sql_subquery (GncSqlBackend* be,
}
g_free (sql);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
for (auto row : *result)
load_slot_for_book_object (be, row, lookup_fn);
}
diff --git a/src/backend/sql/gnc-tax-table-sql.cpp b/src/backend/sql/gnc-tax-table-sql.cpp
index f336ef2..ca22a60 100644
--- a/src/backend/sql/gnc-tax-table-sql.cpp
+++ b/src/backend/sql/gnc-tax-table-sql.cpp
@@ -227,7 +227,6 @@ load_taxtable_entries (GncSqlBackend* be, GncTaxTable* tt)
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
GValue value;
gchar* buf;
- GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
g_return_if_fail (tt != NULL);
@@ -238,10 +237,9 @@ load_taxtable_entries (GncSqlBackend* be, GncTaxTable* tt)
g_value_set_string (&value, guid_buf);
buf = g_strdup_printf ("SELECT * FROM %s WHERE taxtable='%s'",
TTENTRIES_TABLE_NAME, guid_buf);
- stmt = gnc_sql_connection_create_statement_from_sql (be->conn, buf);
+ auto stmt = gnc_sql_connection_create_statement_from_sql (be->conn, buf);
g_free (buf);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
for (auto row : *result)
load_single_ttentry (be, row, tt);
}
@@ -293,14 +291,11 @@ load_single_taxtable (GncSqlBackend* be, GncSqlRow& row,
void
GncSqlTaxTableBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
-
g_return_if_fail (be != NULL);
/* First time, create the query */
- stmt = gnc_sql_create_select_statement (be, TT_TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TT_TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* tt_needing_parents = NULL;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-transaction-sql.cpp b/src/backend/sql/gnc-transaction-sql.cpp
index d64a797..f595eba 100644
--- a/src/backend/sql/gnc-transaction-sql.cpp
+++ b/src/backend/sql/gnc-transaction-sql.cpp
@@ -355,7 +355,7 @@ typedef struct
* @param stmt SQL statement
*/
static void
-query_transactions (GncSqlBackend* be, GncSqlStatement* stmt)
+query_transactions (GncSqlBackend* be, const GncSqlStatementPtr& stmt)
{
g_return_if_fail (be != NULL);
g_return_if_fail (stmt != NULL);
@@ -765,7 +765,6 @@ void gnc_sql_transaction_load_tx_for_account (GncSqlBackend* be,
const GncGUID* guid;
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
gchar* query_sql;
- GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
g_return_if_fail (account != NULL);
@@ -775,12 +774,11 @@ void gnc_sql_transaction_load_tx_for_account (GncSqlBackend* be,
query_sql = g_strdup_printf (
"SELECT DISTINCT t.* FROM %s AS t, %s AS s WHERE s.tx_guid=t.guid AND s.account_guid ='%s'",
TRANSACTION_TABLE, SPLIT_TABLE, guid_buf);
- stmt = gnc_sql_create_statement_from_sql (be, query_sql);
+ auto stmt = gnc_sql_create_statement_from_sql (be, query_sql);
g_free (query_sql);
- if (stmt != NULL)
+ if (stmt != nullptr)
{
query_transactions (be, stmt);
- delete stmt;
}
}
@@ -793,18 +791,14 @@ void gnc_sql_transaction_load_tx_for_account (GncSqlBackend* be,
void
GncSqlTransBackend::load_all (GncSqlBackend* be)
{
- gchar* query_sql;
- GncSqlStatement* stmt;
-
g_return_if_fail (be != NULL);
- query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
- stmt = gnc_sql_create_statement_from_sql (be, query_sql);
+ auto query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
+ auto stmt = gnc_sql_create_statement_from_sql (be, query_sql);
g_free (query_sql);
- if (stmt != NULL)
+ if (stmt != nullptr)
{
query_transactions (be, stmt);
- delete stmt;
}
}
@@ -1033,7 +1027,7 @@ convert_query_term_to_sql (const GncSqlBackend* be, const gchar* fieldName,
typedef struct
{
- GncSqlStatement* stmt;
+ GncSqlStatementPtr stmt;
gboolean has_been_run;
} split_query_info_t;
@@ -1213,8 +1207,7 @@ run_split_query (GncSqlBackend* be, gpointer pQuery)
{
query_transactions (be, query_info->stmt);
query_info->has_been_run = TRUE;
- delete query_info->stmt;
- query_info->stmt = NULL;
+ query_info->stmt = nullptr;
}
}
@@ -1300,7 +1293,6 @@ GSList*
gnc_sql_get_account_balances_slist (GncSqlBackend* be)
{
#if LOAD_TRANSACTIONS_AS_NEEDED
- GncSqlStatement* stmt;
gchar* buf;
GSList* bal_slist = NULL;
@@ -1308,11 +1300,10 @@ gnc_sql_get_account_balances_slist (GncSqlBackend* be)
buf = g_strdup_printf ("SELECT account_guid, reconcile_state, sum(quantity_num) as quantity_num, quantity_denom FROM %s GROUP BY account_guid, reconcile_state, quantity_denom ORDER BY account_guid, reconcile_state",
SPLIT_TABLE);
- stmt = gnc_sql_create_statement_from_sql (be, buf);
- g_assert (stmt != NULL);
+ auto stmt = gnc_sql_create_statement_from_sql (be, buf);
+ g_assert (stmt != nullptr);
g_free (buf);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
acct_balances_t* bal = NULL;
for (auto row : *result)
diff --git a/src/backend/sql/gnc-vendor-sql.cpp b/src/backend/sql/gnc-vendor-sql.cpp
index e2fe425..3c40be7 100644
--- a/src/backend/sql/gnc-vendor-sql.cpp
+++ b/src/backend/sql/gnc-vendor-sql.cpp
@@ -113,13 +113,10 @@ load_single_vendor (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlVendorBackend::load_all (GncSqlBackend* be)
{
- GncSqlStatement* stmt;
-
g_return_if_fail (be != NULL);
- stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
+ auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
- delete stmt;
GList* list = NULL;
for (auto row : *result)
commit 64c1fda6ec1417b9d0dabd937c9981aff0f36261
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Jun 17 11:21:18 2016 -0700
gnc-backend-dbi.cpp: NULL -> nullptr.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 6aa5c0d..a7c7e72 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -138,7 +138,7 @@ struct QofPGSQLBackendProvider : public QofBackendProvider
#if LIBDBI_VERSION >= 900
#define HAVE_LIBDBI_R 1
#define HAVE_LIBDBI_TO_LONGLONG 1
-static dbi_inst dbi_instance = NULL;
+static dbi_inst dbi_instance = nullptr;
#else
#define HAVE_LIBDBI_R 0
#define HAVE_LIBDBI_TO_LONGLONG 0
@@ -238,7 +238,7 @@ static void
gnc_table_slist_free (GSList* table_list)
{
GSList* list;
- for (list = table_list; list != NULL; list = g_slist_next (list))
+ for (list = table_list; list != nullptr; list = g_slist_next (list))
{
g_free (list->data);
}
@@ -249,7 +249,7 @@ static void
gnc_dbi_set_error (GncDbiSqlConnection* dbi_conn, gint last_error,
gint error_repeat, gboolean retry)
{
- g_return_if_fail (dbi_conn != NULL);
+ g_return_if_fail (dbi_conn != nullptr);
dbi_conn->last_error = last_error;
if (error_repeat > 0)
@@ -320,16 +320,16 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
gint result;
- gchar* dirname = NULL;
- gchar* basename = NULL;
- gchar* filepath = NULL;
+ gchar* dirname = nullptr;
+ gchar* basename = nullptr;
+ gchar* filepath = nullptr;
const char* msg = nullptr;
gboolean file_exists;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
- g_return_if_fail (qbe != NULL);
- g_return_if_fail (session != NULL);
- g_return_if_fail (book_id != NULL);
+ g_return_if_fail (qbe != nullptr);
+ g_return_if_fail (session != nullptr);
+ g_return_if_fail (book_id != nullptr);
ENTER (" ");
@@ -355,7 +355,7 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
}
- if (be->conn != NULL)
+ if (be->conn != nullptr)
{
dbi_conn_close (be->conn);
}
@@ -369,7 +369,7 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
be->conn = dbi_conn_new ("sqlite3");
#endif
- if (be->conn == NULL)
+ if (be->conn == nullptr)
{
PERR ("Unable to create sqlite3 dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
@@ -434,7 +434,7 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
{
/* does now, and we don't want to */
dbi_conn_close (be->conn); /* leave it lying around. */
- be->conn = NULL;
+ be->conn = nullptr;
g_unlink (filepath);
}
msg = "Bad DBI Library";
@@ -447,7 +447,7 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
goto exit;
}
- if (be->sql_be.conn != NULL)
+ if (be->sql_be.conn != nullptr)
{
gnc_sql_connection_dispose (be->sql_be.conn);
}
@@ -461,23 +461,23 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session,
PINFO ("logpath=%s", filepath ? filepath : "(null)");
exit:
- if (filepath != NULL) g_free (filepath);
- if (basename != NULL) g_free (basename);
- if (dirname != NULL) g_free (dirname);
+ if (filepath != nullptr) g_free (filepath);
+ if (basename != nullptr) g_free (basename);
+ if (dirname != nullptr) g_free (dirname);
LEAVE ("%s", msg);
}
static GSList*
conn_get_index_list_sqlite3 (dbi_conn conn)
{
- GSList* list = NULL;
+ GSList* list = nullptr;
const gchar* errmsg;
dbi_result result = dbi_conn_query (conn,
"SELECT name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_autoindex%'");
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
g_print ("Index Table Retrieval Error: %s\n", errmsg);
- return NULL;
+ return nullptr;
}
while (dbi_result_next_row (result) != 0)
{
@@ -661,12 +661,12 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
result = dbi_conn_queryf (dcon,
"CREATE TABLE %s ( Hostname varchar(%d), PID int )", lock_table,
GNC_HOST_NAME_MAX);
- if (dbi_conn_error (dcon, NULL))
+ if (dbi_conn_error (dcon, nullptr))
{
const gchar* errstr;
dbi_conn_error (dcon, &errstr);
@@ -675,20 +675,20 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
return FALSE;
}
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
}
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
/* Protect everything with a single transaction to prevent races */
@@ -699,13 +699,13 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
result = dbi_conn_queryf (dcon, "SELECT * FROM %s", lock_table);
if (result && dbi_result_get_numrows (result))
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
if (!ignore_lock)
{
qof_backend_set_error (qbe, ERR_BACKEND_LOCKED);
@@ -722,14 +722,14 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
return FALSE;
}
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
}
/* Add an entry and commit the transaction */
@@ -746,20 +746,20 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
return FALSE;
}
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
result = dbi_conn_query (dcon, "COMMIT");
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
return TRUE;
}
@@ -769,7 +769,7 @@ gnc_dbi_lock_database (QofBackend* qbe, gboolean ignore_lock)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
return FALSE;
}
@@ -779,21 +779,21 @@ gnc_dbi_unlock (QofBackend* qbe)
GncDbiBackend* qe = (GncDbiBackend*)qbe;
dbi_conn dcon = qe->conn;
dbi_result result;
- const gchar* dbname = NULL;
+ const gchar* dbname = nullptr;
- g_return_if_fail (dcon != NULL);
- g_return_if_fail (dbi_conn_error (dcon, NULL) == 0);
+ g_return_if_fail (dcon != nullptr);
+ g_return_if_fail (dbi_conn_error (dcon, nullptr) == 0);
dbname = dbi_conn_get_option (dcon, "dbname");
/* Check if the lock table exists */
- g_return_if_fail (dbname != NULL);
+ g_return_if_fail (dbname != nullptr);
result = dbi_conn_get_table_list (dcon, dbname, lock_table);
if (! (result && dbi_result_get_numrows (result)))
{
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
PWARN ("No lock table in database, so not unlocking it.");
return;
@@ -807,7 +807,7 @@ gnc_dbi_unlock (QofBackend* qbe)
gchar hostname[ GNC_HOST_NAME_MAX + 1 ];
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
memset (hostname, 0, sizeof (hostname));
gethostname (hostname, GNC_HOST_NAME_MAX);
result = dbi_conn_queryf (dcon,
@@ -818,7 +818,7 @@ gnc_dbi_unlock (QofBackend* qbe)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
result = dbi_conn_queryf (dcon, "DELETE FROM %s", lock_table);
if (!result)
@@ -829,20 +829,20 @@ gnc_dbi_unlock (QofBackend* qbe)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
return;
}
else
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
result = dbi_conn_query (dcon, "COMMIT");
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
return;
}
@@ -850,7 +850,7 @@ gnc_dbi_unlock (QofBackend* qbe)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
PWARN ("There was no lock entry in the Lock table");
return;
@@ -858,7 +858,7 @@ gnc_dbi_unlock (QofBackend* qbe)
if (result)
{
dbi_result_free (result);
- result = NULL;
+ result = nullptr;
}
PWARN ("Unable to get a lock on LOCK, so failed to clear the lock entry.");
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
@@ -937,21 +937,21 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
gboolean create, gboolean force)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- gchar* protocol = NULL;
- gchar* host = NULL;
- gchar* dbname = NULL;
- gchar* username = NULL;
- gchar* password = NULL;
- gchar* basename = NULL;
- gchar* translog_path = NULL;
+ gchar* protocol = nullptr;
+ gchar* host = nullptr;
+ gchar* dbname = nullptr;
+ gchar* username = nullptr;
+ gchar* password = nullptr;
+ gchar* basename = nullptr;
+ gchar* translog_path = nullptr;
gint portnum = 0;
gint result;
gboolean success = FALSE;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
- g_return_if_fail (qbe != NULL);
- g_return_if_fail (session != NULL);
- g_return_if_fail (book_id != NULL);
+ g_return_if_fail (qbe != nullptr);
+ g_return_if_fail (session != nullptr);
+ g_return_if_fail (book_id != nullptr);
ENTER (" ");
@@ -964,7 +964,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
// Try to connect to the db. If it doesn't exist and the create
// flag is TRUE, we'll need to connect to the 'mysql' db and execute the
// CREATE DATABASE ddl statement there.
- if (be->conn != NULL)
+ if (be->conn != nullptr)
{
dbi_conn_close (be->conn);
}
@@ -976,7 +976,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
#else
be->conn = dbi_conn_new ("mysql");
#endif
- if (be->conn == NULL)
+ if (be->conn == nullptr)
{
PERR ("Unable to create mysql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
@@ -1055,7 +1055,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
adjust_sql_options (be->conn);
dresult = dbi_conn_queryf (be->conn, "CREATE DATABASE %s CHARACTER SET utf8",
dbname);
- if (dresult == NULL)
+ if (dresult == nullptr)
{
PERR ("Unable to create database '%s'\n", dbname);
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
@@ -1073,7 +1073,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
be->conn = dbi_conn_new ("mysql");
#endif
- if (be->conn == NULL)
+ if (be->conn == nullptr)
{
PERR ("Unable to create mysql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
@@ -1129,7 +1129,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
{
dbi_result dresult;
- if (be->sql_be.conn != NULL)
+ if (be->sql_be.conn != nullptr)
{
gnc_sql_connection_dispose (be->sql_be.conn);
}
@@ -1140,7 +1140,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session,
/* We should now have a proper session set up.
* Let's start logging */
- basename = g_strjoin ("_", protocol, host, username, dbname, NULL);
+ basename = g_strjoin ("_", protocol, host, username, dbname, nullptr);
translog_path = gnc_build_translog_path (basename);
xaccLogSetBaseName (translog_path);
PINFO ("logpath=%s", translog_path ? translog_path : "(null)");
@@ -1160,16 +1160,16 @@ exit:
static GSList*
conn_get_index_list_mysql (dbi_conn conn)
{
- GSList* index_list = NULL;
+ GSList* index_list = nullptr;
dbi_result table_list;
const char* errmsg;
const gchar* dbname = dbi_conn_get_option (conn, "dbname");
- g_return_val_if_fail (conn != NULL, NULL);
- table_list = dbi_conn_get_table_list (conn, dbname, NULL);
+ g_return_val_if_fail (conn != nullptr, nullptr);
+ table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
g_print ("Table Retrieval Error: %s\n", errmsg);
- return NULL;
+ return nullptr;
}
while (dbi_result_next_row (table_list) != 0)
{
@@ -1188,7 +1188,7 @@ conn_get_index_list_mysql (dbi_conn conn)
{
const gchar* index_name = dbi_result_get_string_idx (result, 3);
index_list = g_slist_prepend (index_list, g_strjoin (" ", index_name,
- table_name, NULL));
+ table_name, nullptr));
}
dbi_result_free (result);
}
@@ -1204,7 +1204,7 @@ conn_drop_index_mysql (dbi_conn conn, const gchar* index)
int splitlen = -1;
/* Check if the index split can be valid */
- while (index_table_split[++splitlen] != NULL)
+ while (index_table_split[++splitlen] != nullptr)
{ /* do nothing, just count split members */ }
if (splitlen != 2)
@@ -1245,7 +1245,7 @@ pgsql_error_fn (dbi_conn conn, void* user_data)
else if (g_strrstr (msg,
"server closed the connection unexpectedly")) // Connection lost
{
- if (dbi_conn == NULL)
+ if (dbi_conn == nullptr)
{
PWARN ("DBI Error: Connection lost, connection pointer invalid");
return;
@@ -1293,20 +1293,20 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
gint result = 0;
- gchar* protocol = NULL;
- gchar* host = NULL;
- gchar* dbname = NULL, *dbnamelc = NULL;
- gchar* username = NULL;
- gchar* password = NULL;
- gchar* basename = NULL;
- gchar* translog_path = NULL;
+ gchar* protocol = nullptr;
+ gchar* host = nullptr;
+ gchar* dbname = nullptr, *dbnamelc = nullptr;
+ gchar* username = nullptr;
+ gchar* password = nullptr;
+ gchar* basename = nullptr;
+ gchar* translog_path = nullptr;
gboolean success = FALSE;
gint portnum = 0;
GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
- g_return_if_fail (qbe != NULL);
- g_return_if_fail (session != NULL);
- g_return_if_fail (book_id != NULL);
+ g_return_if_fail (qbe != nullptr);
+ g_return_if_fail (session != nullptr);
+ g_return_if_fail (book_id != nullptr);
ENTER (" ");
@@ -1326,7 +1326,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
// Try to connect to the db. If it doesn't exist and the create
// flag is TRUE, we'll need to connect to the 'postgres' db and execute the
// CREATE DATABASE ddl statement there.
- if (be->conn != NULL)
+ if (be->conn != nullptr)
{
dbi_conn_close (be->conn);
}
@@ -1340,7 +1340,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
be->conn = dbi_conn_new ("pgsql");
#endif
- if (be->conn == NULL)
+ if (be->conn == nullptr)
{
PERR ("Unable to create pgsql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
@@ -1417,7 +1417,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
}
dresult = dbi_conn_queryf (be->conn,
"CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'", dbnamelc);
- if (dresult == NULL)
+ if (dresult == nullptr)
{
PERR ("Unable to create database '%s'\n", dbname);
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
@@ -1437,7 +1437,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
be->conn = dbi_conn_new ("pgsql");
#endif
- if (be->conn == NULL)
+ if (be->conn == nullptr)
{
PERR ("Unable to create pgsql dbi connection\n");
qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL);
@@ -1490,7 +1490,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
}
if (success)
{
- if (be->sql_be.conn != NULL)
+ if (be->sql_be.conn != nullptr)
{
gnc_sql_connection_dispose (be->sql_be.conn);
}
@@ -1501,7 +1501,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session,
/* We should now have a proper session set up.
* Let's start logging */
- basename = g_strjoin ("_", protocol, host, username, dbname, NULL);
+ basename = g_strjoin ("_", protocol, host, username, dbname, nullptr);
translog_path = gnc_build_translog_path (basename);
xaccLogSetBaseName (translog_path);
PINFO ("logpath=%s", translog_path ? translog_path : "(null)");
@@ -1522,7 +1522,7 @@ exit:
static GSList*
conn_get_index_list_pgsql (dbi_conn conn)
{
- GSList* list = NULL;
+ GSList* list = nullptr;
const gchar* errmsg;
dbi_result result;
PINFO ("Retrieving postgres index list\n");
@@ -1531,7 +1531,7 @@ conn_get_index_list_pgsql (dbi_conn conn)
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
g_print ("Index Table Retrieval Error: %s\n", errmsg);
- return NULL;
+ return nullptr;
}
while (dbi_result_next_row (result) != 0)
{
@@ -1560,20 +1560,20 @@ gnc_dbi_session_end (QofBackend* be_start)
{
GncDbiBackend* be = (GncDbiBackend*)be_start;
- g_return_if_fail (be_start != NULL);
+ g_return_if_fail (be_start != nullptr);
ENTER (" ");
- if (be->conn != NULL)
+ if (be->conn != nullptr)
{
gnc_dbi_unlock (be_start);
dbi_conn_close (be->conn);
- be->conn = NULL;
+ be->conn = nullptr;
}
- if (be->sql_be.conn != NULL)
+ if (be->sql_be.conn != nullptr)
{
gnc_sql_connection_dispose (be->sql_be.conn);
- be->sql_be.conn = NULL;
+ be->sql_be.conn = nullptr;
}
gnc_sql_finalize_version_info (&be->sql_be);
@@ -1583,10 +1583,10 @@ gnc_dbi_session_end (QofBackend* be_start)
static void
gnc_dbi_destroy_backend (QofBackend* be)
{
- g_return_if_fail (be != NULL);
+ g_return_if_fail (be != nullptr);
/* Stop transaction logging */
- xaccLogSetBaseName (NULL);
+ xaccLogSetBaseName (nullptr);
qof_backend_destroy (be);
@@ -1609,14 +1609,14 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- g_return_if_fail (qbe != NULL);
- g_return_if_fail (book != NULL);
+ g_return_if_fail (qbe != nullptr);
+ g_return_if_fail (book != nullptr);
ENTER ("be=%p, book=%p", be, book);
if (loadType == LOAD_TYPE_INITIAL_LOAD)
{
- g_assert (be->primary_book == NULL);
+ g_assert (be->primary_book == nullptr);
be->primary_book = book;
// Set up table version information
@@ -1664,7 +1664,7 @@ save_may_clobber_data (QofBackend* qbe)
/* Data may be clobbered iff the number of tables != 0 */
dbname = dbi_conn_get_option (be->conn, "dbname");
- result = dbi_conn_get_table_list (be->conn, dbname, NULL);
+ result = dbi_conn_get_table_list (be->conn, dbname, nullptr);
if (result)
{
retval = dbi_result_get_numrows (result) > 0;
@@ -1678,7 +1678,7 @@ conn_table_manage_backup (GncDbiSqlConnection* conn,
gchar* table_name, TableOpType op)
{
gchar* new_name = g_strdup_printf ("%s_%s", table_name, "back");
- dbi_result result = NULL;
+ dbi_result result = nullptr;
switch (op)
{
case backup:
@@ -1733,15 +1733,15 @@ conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
GSList* node;
gboolean result = TRUE;
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (sql_conn);
- GSList* full_table_name_list = NULL;
+ GSList* full_table_name_list = nullptr;
const gchar* dbname = dbi_conn_get_option (conn->conn, "dbname");
- g_return_val_if_fail (table_name_list != NULL, FALSE);
+ g_return_val_if_fail (table_name_list != nullptr, FALSE);
if (op == rollback)
full_table_name_list =
conn->provider->get_table_list (conn->conn, dbname);
- for (node = table_name_list; node != NULL && result; node = node->next)
+ for (node = table_name_list; node != nullptr && result; node = node->next)
{
gchar* table_name = (gchar*)node->data;
dbi_result result;
@@ -1780,7 +1780,7 @@ conn_table_operation (GncSqlConnection* sql_conn, GSList* table_name_list,
}
}
while (conn->retry);
- if (result != NULL)
+ if (result != nullptr)
{
if (dbi_result_free (result) < 0)
{
@@ -1809,10 +1809,10 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
GncDbiSqlConnection* conn = (GncDbiSqlConnection*) (((GncSqlBackend*)
be)->conn);
GSList* table_list, *index_list, *iter;
- const gchar* dbname = NULL;
+ const gchar* dbname = nullptr;
- g_return_if_fail (be != NULL);
- g_return_if_fail (book != NULL);
+ g_return_if_fail (be != nullptr);
+ g_return_if_fail (book != nullptr);
ENTER ("book=%p, primary=%p", book, be->primary_book);
dbname = dbi_conn_get_option (be->conn, "dbname");
@@ -1828,7 +1828,7 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
return;
}
index_list = conn->provider->get_index_list (conn->conn);
- for (iter = index_list; iter != NULL; iter = g_slist_next (iter))
+ for (iter = index_list; iter != nullptr; iter = g_slist_next (iter))
{
const char* errmsg;
conn->provider->drop_index (conn->conn, static_cast<char*> (iter->data));
@@ -1867,8 +1867,8 @@ gnc_dbi_begin_edit (QofBackend* qbe, QofInstance* inst)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- g_return_if_fail (be != NULL);
- g_return_if_fail (inst != NULL);
+ g_return_if_fail (be != nullptr);
+ g_return_if_fail (inst != nullptr);
gnc_sql_begin_edit (&be->sql_be, inst);
}
@@ -1878,8 +1878,8 @@ gnc_dbi_rollback_edit (QofBackend* qbe, QofInstance* inst)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- g_return_if_fail (be != NULL);
- g_return_if_fail (inst != NULL);
+ g_return_if_fail (be != nullptr);
+ g_return_if_fail (inst != nullptr);
gnc_sql_rollback_edit (&be->sql_be, inst);
}
@@ -1889,8 +1889,8 @@ gnc_dbi_commit_edit (QofBackend* qbe, QofInstance* inst)
{
GncDbiBackend* be = (GncDbiBackend*)qbe;
- g_return_if_fail (be != NULL);
- g_return_if_fail (inst != NULL);
+ g_return_if_fail (be != nullptr);
+ g_return_if_fail (inst != nullptr);
gnc_sql_commit_edit (&be->sql_be, inst);
}
@@ -1915,8 +1915,8 @@ init_sql_backend (GncDbiBackend* dbi_be)
be->rollback = gnc_dbi_rollback_edit;
/* The gda backend will not be multi-user (for now)... */
- be->events_pending = NULL;
- be->process_events = NULL;
+ be->events_pending = nullptr;
+ be->process_events = nullptr;
/* The SQL/DBI backend doesn't need to be synced until it is
* configured for multiuser access. */
@@ -1930,12 +1930,12 @@ init_sql_backend (GncDbiBackend* dbi_be)
be->run_query = nullptr;
be->free_query = nullptr;
- be->export_fn = NULL;
+ be->export_fn = nullptr;
gnc_sql_init (&dbi_be->sql_be);
- dbi_be->sql_be.conn = NULL;
- dbi_be->sql_be.book = NULL;
+ dbi_be->sql_be.conn = nullptr;
+ dbi_be->sql_be.book = nullptr;
}
static QofBackend*
@@ -1948,7 +1948,7 @@ new_backend (void (*session_begin) (QofBackend*, QofSession*, const gchar*,
QofBackend* be;
dbi_be = g_new0 (GncDbiBackend, 1);
- g_assert (dbi_be != NULL);
+ g_assert (dbi_be != nullptr);
be = (QofBackend*)dbi_be;
qof_backend_init (be);
@@ -1992,14 +1992,14 @@ QofSQLITEBackendProvider::type_check(const char *uri)
gchar* filename;
// BAD if the path is null
- g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (uri != nullptr, FALSE);
filename = gnc_uri_get_path (uri);
f = g_fopen (filename, "r");
g_free (filename);
// OK if the file doesn't exist - new file
- if (f == NULL)
+ if (f == nullptr)
{
PINFO ("doesn't exist (errno=%d) -> DBI", errno);
return TRUE;
@@ -2035,7 +2035,7 @@ gnc_module_init_backend_dbi (void)
/* Initialize libdbi and see which drivers are available. Only register qof backends which
have drivers available. */
driver_dir = g_getenv ("GNC_DBD_DIR");
- if (driver_dir == NULL)
+ if (driver_dir == nullptr)
{
PINFO ("GNC_DBD_DIR not set: using libdbi built-in default\n");
}
@@ -2050,7 +2050,7 @@ gnc_module_init_backend_dbi (void)
#endif
if (num_drivers <= 0)
{
- gchar* dir = g_build_filename (gnc_path_get_libdir (), "dbd", NULL);
+ gchar* dir = g_build_filename (gnc_path_get_libdir (), "dbd", nullptr);
#if HAVE_LIBDBI_R
if (dbi_instance)
return;
@@ -2066,7 +2066,7 @@ gnc_module_init_backend_dbi (void)
}
else
{
- dbi_driver driver = NULL;
+ dbi_driver driver = nullptr;
PINFO ("%d DBD drivers found\n", num_drivers);
do
@@ -2077,7 +2077,7 @@ gnc_module_init_backend_dbi (void)
driver = dbi_driver_list (driver);
#endif
- if (driver != NULL)
+ if (driver != nullptr)
{
const gchar* name = dbi_driver_get_name (driver);
@@ -2096,7 +2096,7 @@ gnc_module_init_backend_dbi (void)
}
}
}
- while (driver != NULL);
+ while (driver != nullptr);
}
if (have_sqlite3_driver)
@@ -2148,7 +2148,7 @@ gnc_module_finalize_backend_dbi (void)
if (dbi_instance)
{
dbi_shutdown_r (dbi_instance);
- dbi_instance = NULL;
+ dbi_instance = nullptr;
}
#else
dbi_shutdown ();
@@ -2384,7 +2384,7 @@ conn_execute_nonselect_statement (GncSqlConnection* conn,
result = dbi_conn_query (dbi_conn->conn, stmt->to_sql());
}
while (dbi_conn->retry);
- if (result == NULL)
+ if (result == nullptr && dbi_conn->last_error)
{
PERR ("Error executing SQL %s\n", stmt->to_sql());
return -1;
@@ -2414,8 +2414,8 @@ conn_does_table_exist (GncSqlConnection* conn, const gchar* table_name)
const gchar* dbname;
gint status;
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
+ g_return_val_if_fail (conn != nullptr, FALSE);
+ g_return_val_if_fail (table_name != nullptr, FALSE);
dbname = dbi_conn_get_option (dbi_conn->conn, "dbname");
tables = dbi_conn_get_table_list (dbi_conn->conn, dbname, table_name);
@@ -2461,7 +2461,7 @@ conn_begin_transaction (GncSqlConnection* conn)
}
while (dbi_conn->retry);
- success = (result != NULL);
+ success = (result != nullptr);
status = dbi_result_free (result);
if (status < 0)
{
@@ -2488,7 +2488,7 @@ conn_rollback_transaction (GncSqlConnection* conn)
DEBUG ("ROLLBACK\n");
const char* command = "ROLLBACK";
result = dbi_conn_query (dbi_conn->conn, command);
- success = (result != NULL);
+ success = (result != nullptr);
status = dbi_result_free (result);
if (status < 0)
@@ -2515,7 +2515,7 @@ conn_commit_transaction (GncSqlConnection* conn)
DEBUG ("COMMIT\n");
result = dbi_conn_queryf (dbi_conn->conn, "COMMIT");
- success = (result != NULL);
+ success = (result != nullptr);
status = dbi_result_free (result);
if (status < 0)
@@ -2538,9 +2538,9 @@ create_index_ddl (GncSqlConnection* conn, const char* index_name,
{
GString* ddl;
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (index_name != NULL, NULL);
- g_return_val_if_fail (table_name != NULL, NULL);
+ g_return_val_if_fail (conn != nullptr, nullptr);
+ g_return_val_if_fail (index_name != nullptr, nullptr);
+ g_return_val_if_fail (table_name != nullptr, nullptr);
ddl = g_string_new ("");
g_string_printf (ddl, "CREATE INDEX %s ON %s (", index_name, table_name);
@@ -2565,8 +2565,8 @@ add_columns_ddl(GncSqlConnection* conn,
GString* ddl;
GncDbiSqlConnection* dbi_conn = (GncDbiSqlConnection*)conn;
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (table_name != NULL, NULL);
+ g_return_val_if_fail (conn != nullptr, nullptr);
+ g_return_val_if_fail (table_name != nullptr, nullptr);
ddl = g_string_new ("");
g_string_printf (ddl, "ALTER TABLE %s ", table_name);
@@ -2637,8 +2637,8 @@ conn_create_table_ddl_sqlite3 (GncSqlConnection* conn,
GString* ddl;
unsigned int col_num = 0;
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (table_name != NULL, NULL);
+ g_return_val_if_fail (conn != nullptr, nullptr);
+ g_return_val_if_fail (table_name != nullptr, nullptr);
ddl = g_string_new ("");
g_string_printf (ddl, "CREATE TABLE %s (", table_name);
@@ -2719,8 +2719,8 @@ conn_create_table_ddl_mysql (GncSqlConnection* conn, const gchar* table_name,
GString* ddl;
unsigned int col_num = 0;
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (table_name != NULL, NULL);
+ g_return_val_if_fail (conn != nullptr, nullptr);
+ g_return_val_if_fail (table_name != nullptr, nullptr);
ddl = g_string_new ("");
g_string_printf (ddl, "CREATE TABLE %s (", table_name);
@@ -2801,8 +2801,8 @@ conn_create_table_ddl_pgsql (GncSqlConnection* conn, const gchar* table_name,
GString* ddl;
unsigned int col_num = 0;
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (table_name != NULL, NULL);
+ g_return_val_if_fail (conn != nullptr, nullptr);
+ g_return_val_if_fail (table_name != nullptr, nullptr);
ddl = g_string_new ("");
g_string_printf (ddl, "CREATE TABLE %s (", table_name);
@@ -2827,11 +2827,11 @@ conn_create_table (GncSqlConnection* conn, const gchar* table_name,
gchar* ddl;
dbi_result result;
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
+ g_return_val_if_fail (conn != nullptr, FALSE);
+ g_return_val_if_fail (table_name != nullptr, FALSE);
ddl = dbi_conn->provider->create_table_ddl(conn, table_name, info_vec);
- if (ddl != NULL)
+ if (ddl != nullptr)
{
gint status;
@@ -2861,12 +2861,12 @@ conn_create_index(GncSqlConnection* conn, const char* index_name,
gchar* ddl;
dbi_result result;
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (index_name != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
+ g_return_val_if_fail (conn != nullptr, FALSE);
+ g_return_val_if_fail (index_name != nullptr, FALSE);
+ g_return_val_if_fail (table_name != nullptr, FALSE);
ddl = create_index_ddl (conn, index_name, table_name, col_table);
- if (ddl != NULL)
+ if (ddl != nullptr)
{
gint status;
@@ -2896,11 +2896,11 @@ conn_add_columns_to_table(GncSqlConnection* conn, const char* table_name,
gchar* ddl;
dbi_result result;
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (table_name != NULL, FALSE);
+ g_return_val_if_fail (conn != nullptr, FALSE);
+ g_return_val_if_fail (table_name != nullptr, FALSE);
ddl = add_columns_ddl(conn, table_name, info_vec);
- if (ddl == NULL)
+ if (ddl == nullptr)
return FALSE;
DEBUG ("SQL: %s\n", ddl);
@@ -2931,7 +2931,7 @@ conn_quote_string (const GncSqlConnection* conn, const char* unquoted_str)
}
else
{
- return NULL;
+ return nullptr;
}
}
@@ -2939,9 +2939,9 @@ static GSList*
conn_get_table_list (dbi_conn conn, const gchar* dbname)
{
dbi_result tables;
- GSList* list = NULL;
+ GSList* list = nullptr;
- tables = dbi_conn_get_table_list (conn, dbname, NULL);
+ tables = dbi_conn_get_table_list (conn, dbname, nullptr);
while (dbi_result_next_row (tables) != 0)
{
const gchar* table_name;
@@ -2962,12 +2962,12 @@ conn_get_table_list_sqlite3 (dbi_conn conn, const gchar* dbname)
* its own use. */
GSList* list = conn_get_table_list (conn, dbname);
change_made = TRUE;
- while (list != NULL && change_made)
+ while (list != nullptr && change_made)
{
GSList* node;
change_made = FALSE;
- for (node = list; node != NULL; node = node->next)
+ for (node = list; node != nullptr; node = node->next)
{
const gchar* table_name = (const gchar*)node->data;
@@ -2991,12 +2991,12 @@ conn_get_table_list_pgsql (dbi_conn conn, const gchar* dbname)
/* Return the list, but remove the tables that postgresql adds from the information schema. */
GSList* list = conn_get_table_list (conn, dbname);
change_made = TRUE;
- while (list != NULL && change_made)
+ while (list != nullptr && change_made)
{
GSList* node;
change_made = FALSE;
- for (node = list; node != NULL; node = node->next)
+ for (node = list; node != nullptr; node = node->next)
{
const gchar* table_name = (const gchar*)node->data;
@@ -3041,7 +3041,7 @@ conn_test_dbi_library (dbi_conn conn)
result = dbi_conn_query (conn, "CREATE TEMPORARY TABLE numtest "
"( test_int BIGINT, test_unsigned BIGINT,"
" test_double FLOAT8 )");
- if (result == NULL)
+ if (result == nullptr)
{
PWARN ("Test_DBI_Library: Create table failed");
return GNC_DBI_FAIL_SETUP;
@@ -3053,7 +3053,7 @@ conn_test_dbi_library (dbi_conn conn)
testlonglong, testulonglong, doublestr);
result = dbi_conn_query (conn, querystr);
g_free (querystr);
- if (result == NULL)
+ if (result == nullptr)
{
PWARN ("Test_DBI_Library: Failed to insert test row into table");
return GNC_DBI_FAIL_SETUP;
@@ -3061,7 +3061,7 @@ conn_test_dbi_library (dbi_conn conn)
dbi_result_free (result);
gnc_push_locale (LC_NUMERIC, "C");
result = dbi_conn_query (conn, "SELECT * FROM numtest");
- if (result == NULL)
+ if (result == nullptr)
{
const char* errmsg;
dbi_conn_error (conn, &errmsg);
@@ -3112,7 +3112,7 @@ create_dbi_connection (provider_functions_t* provider,
GncDbiSqlConnection* dbi_conn;
dbi_conn = g_new0 (GncDbiSqlConnection, 1);
- g_assert (dbi_conn != NULL);
+ g_assert (dbi_conn != nullptr);
dbi_conn->base.dispose = conn_dispose;
dbi_conn->base.executeSelectStatement = conn_execute_select_statement;
commit 92f2f2765eaa701176e11559be9b0d29f525cdbd
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Jun 17 10:28:02 2016 -0700
Replace the ptr-to-func GncSqlObjectBackend struct with a class hierarchy.
Can't template them because we need to iterate on the collection when loading.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 2d70f7a..6aa5c0d 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -294,12 +294,9 @@ create_tables(const OBEEntry& entry, GncDbiBackend* be)
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(obe->is_version (GNC_SQL_BACKEND_VERSION));
- if (obe->create_tables != nullptr)
- {
- (obe->create_tables)(&be->sql_be);
- }
+ obe->create_tables (&be->sql_be);
}
static void
@@ -1926,9 +1923,12 @@ init_sql_backend (GncDbiBackend* dbi_be)
be->sync = gnc_dbi_safe_sync_all;
be->safe_sync = gnc_dbi_safe_sync_all;
- be->compile_query = gnc_sql_compile_query;
- be->run_query = gnc_sql_run_query;
- be->free_query = gnc_sql_free_query;
+// be->compile_query = gnc_sql_compile_query;
+// be->run_query = gnc_sql_run_query;
+// be->free_query = gnc_sql_free_query;
+ be->compile_query = nullptr;
+ be->run_query = nullptr;
+ be->free_query = nullptr;
be->export_fn = NULL;
diff --git a/src/backend/sql/gnc-account-sql.cpp b/src/backend/sql/gnc-account-sql.cpp
index a9f3149..bdb3bff 100644
--- a/src/backend/sql/gnc-account-sql.cpp
+++ b/src/backend/sql/gnc-account-sql.cpp
@@ -91,6 +91,18 @@ 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;
+};
+
+
+
typedef struct
{
Account* pAccount;
@@ -198,8 +210,8 @@ load_single_account (GncSqlBackend* be, GncSqlRow& row,
return pAccount;
}
-static void
-load_all_accounts (GncSqlBackend* be)
+void
+GncSqlAccountBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt = NULL;
QofBook* pBook;
@@ -308,23 +320,8 @@ load_all_accounts (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_account_tables (GncSqlBackend* be)
-{
- gint version;
-
- g_return_if_fail (be != NULL);
-
- version = gnc_sql_get_table_version (be, TABLE_NAME);
- if (version == 0)
- {
- (void)gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
- }
-}
-
-/* ================================================================= */
-gboolean
-gnc_sql_save_account (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlAccountBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
Account* pAcc = GNC_ACCOUNT (inst);
const GncGUID* guid;
@@ -425,19 +422,8 @@ GncSqlColumnTableEntryImpl<CT_ACCOUNTREF>::add_to_query(const GncSqlBackend* be,
void
gnc_sql_init_account_handler (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_ACCOUNT,
- gnc_sql_save_account, /* commit */
- load_all_accounts, /* initial_load */
- create_account_tables, /* create_tables */
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
- NULL /* write */
- };
-
+ static GncSqlAccountBackend be_data{
+ GNC_SQL_BACKEND_VERSION, GNC_ID_ACCOUNT, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index d03ca29..b4b3042 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -136,7 +136,7 @@ gnc_sql_register_backend(OBEEntry&& entry)
void
gnc_sql_register_backend(GncSqlObjectBackendPtr obe)
{
- backend_registry.emplace_back(make_tuple(std::string{obe->type_name}, obe));
+ backend_registry.emplace_back(make_tuple(std::string{obe->type()}, obe));
}
const OBEVec&
@@ -144,6 +144,21 @@ 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);
+ });
+ auto obe = std::get<1>(*entry);
+ if (entry != backend_registry.end())
+ return obe;
+ return nullptr;
+}
+
void
gnc_sql_init(GncSqlBackend* be)
{
@@ -164,13 +179,9 @@ create_tables(const OBEEntry& entry, GncSqlBackend* be)
std::string type;
GncSqlObjectBackendPtr obe = nullptr;
std::tie(type, obe) = entry;
- g_return_if_fail (obe->version == GNC_SQL_BACKEND_VERSION);
-
- if (obe->create_tables != nullptr)
- {
- update_progress(be);
- (obe->create_tables)(be);
- }
+ g_return_if_fail (obe->is_version (GNC_SQL_BACKEND_VERSION));
+ update_progress(be);
+ obe->create_tables(be);
}
/* ================================================================= */
@@ -195,7 +206,7 @@ initial_load(const OBEEntry& entry, GncSqlBackend* be)
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(obe->is_version (GNC_SQL_BACKEND_VERSION));
/* Don't need to load anything if it has already been loaded with
* the fixed order.
@@ -205,8 +216,7 @@ initial_load(const OBEEntry& entry, GncSqlBackend* be)
if (std::find(other_load_order.begin(), other_load_order.end(),
type) != other_load_order.end()) return;
- if (obe->initial_load != nullptr)
- (obe->initial_load)(be);
+ obe->load_all (be);
}
void
@@ -243,34 +253,20 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
/* Load any initial stuff. Some of this needs to happen in a certain order */
for (auto type : fixed_load_order)
{
- 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)
+ auto obe = gnc_sql_get_object_backend(type);
+ if (obe)
{
update_progress(be);
- (obe->initial_load)(be);
+ obe->load_all (be);
}
}
for (auto type : other_load_order)
{
- 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())
- continue;
- auto obe = std::get<1>(*entry);
- if (entry != backend_registry.end() &&
- obe->initial_load != nullptr)
+ auto obe = gnc_sql_get_object_backend(type);
+ if (obe)
{
update_progress(be);
- (obe->initial_load)(be);
+ obe->load_all (be);
}
}
@@ -287,7 +283,8 @@ gnc_sql_load (GncSqlBackend* be, QofBook* book, QofBackendLoadType loadType)
else if (loadType == LOAD_TYPE_LOAD_ALL)
{
// Load all transactions
- gnc_sql_transaction_load_all_tx (be);
+ auto obe = gnc_sql_get_object_backend (GNC_ID_TRANS);
+ obe->load_all (be);
}
be->loading = FALSE;
@@ -315,13 +312,14 @@ write_account_tree (GncSqlBackend* be, Account* root)
g_return_val_if_fail (be != NULL, FALSE);
g_return_val_if_fail (root != NULL, FALSE);
- is_ok = gnc_sql_save_account (be, QOF_INSTANCE (root));
+ auto obe = gnc_sql_get_object_backend (GNC_ID_ACCOUNT);
+ is_ok = obe->commit (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 = gnc_sql_save_account (be, QOF_INSTANCE (GNC_ACCOUNT (node->data)));
+ is_ok = obe->commit(be, QOF_INSTANCE (GNC_ACCOUNT (node->data)));
if (!is_ok) break;
}
g_list_free (descendants);
@@ -349,36 +347,34 @@ write_accounts (GncSqlBackend* be)
return is_ok;
}
-static int
+static gboolean
write_tx (Transaction* tx, gpointer data)
{
- write_objects_t* s = (write_objects_t*)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->is_ok = gnc_sql_save_transaction (s->be, QOF_INSTANCE (tx));
- update_progress (s->be);
-
- if (s->is_ok)
+ 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))
{
- return 0;
- }
- else
- {
- return 1;
+ s->is_ok = splitbe->commit(s->be, QOF_INSTANCE(split_node->data));
}
+ update_progress (s->be);
+ return (s->is_ok ? 0 : 1);
}
static gboolean
write_transactions (GncSqlBackend* be)
{
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
- data.be = be;
- data.is_ok = TRUE;
+ auto obe = gnc_sql_get_object_backend(GNC_ID_TRANS);
+ write_objects_t data{be, true, obe};
+
(void)xaccAccountTreeForEachTransaction (
gnc_book_get_root_account (be->book), write_tx, &data);
update_progress (be);
@@ -388,14 +384,11 @@ write_transactions (GncSqlBackend* be)
static gboolean
write_template_transactions (GncSqlBackend* be)
{
- Account* ra;
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
- data.is_ok = TRUE;
- data.be = be;
- ra = gnc_book_get_template_root (be->book);
+ auto obe = gnc_sql_get_object_backend(GNC_ID_TRANS);
+ write_objects_t data{be, true, obe};
+ auto ra = gnc_book_get_template_root (be->book);
if (gnc_account_n_descendants (ra) > 0)
{
(void)xaccAccountTreeForEachTransaction (ra, write_tx, &data);
@@ -415,11 +408,12 @@ write_schedXactions (GncSqlBackend* be)
g_return_val_if_fail (be != NULL, FALSE);
schedXactions = gnc_book_get_schedxactions (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 = gnc_sql_save_schedxaction (be, QOF_INSTANCE (tmpSX));
+ is_ok = obe->commit (be, QOF_INSTANCE (tmpSX));
}
update_progress (be);
@@ -427,21 +421,6 @@ write_schedXactions (GncSqlBackend* be)
}
static void
-write(const OBEEntry& entry, GncSqlBackend* be)
-{
- std::string type;
- GncSqlObjectBackendPtr obe = nullptr;
- std::tie(type, obe) = entry;
- g_return_if_fail (obe->version == GNC_SQL_BACKEND_VERSION);
-
- if (obe->write != nullptr)
- {
- (void)(obe->write)(be);
- update_progress(be);
- }
-}
-
-static void
update_progress (GncSqlBackend* be)
{
if (be->be.percentage != NULL)
@@ -486,7 +465,8 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
//write_commodities( be, book );
if (is_ok)
{
- is_ok = gnc_sql_save_book (be, QOF_INSTANCE (book));
+ auto obe = gnc_sql_get_object_backend(GNC_ID_BOOK);
+ is_ok = obe->commit (be, QOF_INSTANCE (book));
}
if (is_ok)
{
@@ -507,7 +487,7 @@ gnc_sql_sync_all (GncSqlBackend* be, QofBook* book)
if (is_ok)
{
for (auto entry : backend_registry)
- write(entry, be);
+ std::get<1>(entry)->write (be);
}
if (is_ok)
{
@@ -561,7 +541,7 @@ commit(const OBEEntry& entry, sql_backend* be_data)
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 (obe->is_version (GNC_SQL_BACKEND_VERSION));
/* If this has already been handled, or is not the correct
* handler, return
@@ -569,11 +549,8 @@ commit(const OBEEntry& entry, sql_backend* be_data)
if (type != std::string{be_data->inst->e_type}) return;
if (be_data->is_known) return;
- if (obe->commit != nullptr)
- {
- be_data->is_ok = (obe->commit)(be_data->be, be_data->inst);
- be_data->is_known = TRUE;
- }
+ be_data->is_ok = obe->commit (be_data->be, be_data->inst);
+ be_data->is_known = TRUE;
}
/* Commit_edit handler - find the correct backend handler for this object
@@ -823,26 +800,23 @@ handle_and_term (QofQueryTerm* pTerm, GString* sql)
g_string_append (sql, ")");
}
-
+#if 0 //The query compilation code was never tested so it isn't implemnted for GncSqlObjectBackend.
static void
compile_query(const OBEEntry& entry, sql_backend* be_data)
{
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 (obe->is_version (GNC_SQL_BACKEND_VERSION));
// Is this the right item?
if (type != std::string{be_data->pQueryInfo->searchObj}) return;
if (be_data->is_ok) return;
- if (obe->compile_query != nullptr)
- {
- be_data->pQueryInfo->pCompiledQuery = (obe->compile_query)(
- be_data->be,
- be_data->pQuery);
- be_data->is_ok = TRUE;
- }
+ be_data->pQueryInfo->pCompiledQuery = (obe->compile_query)(
+ be_data->be,
+ be_data->pQuery);
+ be_data->is_ok = TRUE;
}
gchar* gnc_sql_compile_query_to_sql (GncSqlBackend* be, QofQuery* query);
@@ -1052,7 +1026,7 @@ gnc_sql_run_query (QofBackend* pBEnd, gpointer pQuery)
LEAVE ("");
}
-
+#endif //if 0: query creation isn't used yet, code never tested.
/* ================================================================= */
/* Order in which business objects need to be loaded */
static const StrVec business_fixed_load_order =
@@ -2199,10 +2173,8 @@ build_delete_statement (GncSqlBackend* be,
}
/* ================================================================= */
-gboolean
-gnc_sql_commit_standard_item (GncSqlBackend* be, QofInstance* inst,
- const gchar* tableName, QofIdTypeConst obj_name,
- const EntryVec& col_table)
+bool
+GncSqlObjectBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
const GncGUID* guid;
gboolean is_infant;
@@ -2222,7 +2194,8 @@ gnc_sql_commit_standard_item (GncSqlBackend* be, QofInstance* inst,
{
op = OP_DB_UPDATE;
}
- is_ok = gnc_sql_do_db_operation (be, op, tableName, obj_name, inst, col_table);
+ is_ok = gnc_sql_do_db_operation (be, op, m_table_name.c_str(),
+ m_type_name.c_str(), inst, m_col_table);
if (is_ok)
{
@@ -2280,6 +2253,19 @@ gnc_sql_create_table (GncSqlBackend* be, const char* table_name,
return ok;
}
+void
+GncSqlObjectBackend::create_tables (GncSqlBackend* be)
+{
+ g_return_if_fail (be != nullptr);
+ int version = gnc_sql_get_table_version (be, m_table_name.c_str());
+ if (version == 0) //No tables, otherwise version will be >= 1.
+ gnc_sql_create_table (be, m_table_name.c_str(),
+ m_version, m_col_table);
+ else if (version != m_version)
+ PERR("Version mismatch in table %s, expecting %d but backend is %d."
+ "Table creation aborted.", m_table_name.c_str(), m_version, version);
+}
+
gboolean
gnc_sql_create_temp_table (const GncSqlBackend* be, const gchar* table_name,
const EntryVec& col_table)
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 5cb0279..78fc339 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -282,51 +282,100 @@ inline bool operator==(const GncSqlRow& lr, const GncSqlRow& rr) {
return !(lr != rr);
}
+#define GNC_SQL_BACKEND "gnc:sql:1"
+#define GNC_SQL_BACKEND_VERSION 1
+
/**
- * @struct GncSqlObjectBackend
- *
- * Struct used to handle a specific engine object type for an SQL 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
- * create_tables() - create any db tables
- * compile_query() - compile a backend object query
- * run_query() - run a compiled query
- * free_query() - free a compiled query
- * write() - write all objects
+ * Encapsulates per-class table schema with functions to load, create a table,
+ * commit a changed front-end object (note that database transaction semantics
+ * are not yet implemented; edit/commit applies to the front-end object!) and
+ * write all front-end objects of the type to the database. Additional functions
+ * for creating and runing queries existed but were unused and untested. They've
+ * been temporarily removed until the front end is ready to use them.
*/
-typedef struct
+class GncSqlObjectBackend
{
- 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
+public:
+ GncSqlObjectBackend (int version, const std::string& type,
+ const std::string& table, const EntryVec& vec) :
+ m_table_name{table}, m_version{version}, m_type_name{type},
+ m_col_table{vec} {}
+ /**
+ * Load all objects of m_type in the database into memory.
+ * @param be The GncSqlBackend containing the database connection.
*/
- gboolean (*commit) (GncSqlBackend* be, QofInstance* inst);
- /** Load all objects of this type from the database */
- void (*initial_load) (GncSqlBackend* be);
- /** Create database tables for this object */
- void (*create_tables) (GncSqlBackend* be);
- /** Compile a query on these objects */
- gpointer (*compile_query) (GncSqlBackend* be, QofQuery* pQuery);
- /** Run a query on these objects */
- void (*run_query) (GncSqlBackend* be, gpointer pQuery);
- /** Free a query on these objects */
- void (*free_query) (GncSqlBackend* be, gpointer pQuery);
- /** Write all objects of this type to the database
- * @return TRUE if successful, FALSE if error
+ virtual void load_all (GncSqlBackend*) = 0;
+ /**
+ * Conditionally create or update a database table from m_col_table. The
+ * condition is the version returned by querying the database's version
+ * table: If it's 0 then the table wasn't found and will be created; All
+ * tables areat least version 1. If the database's version is less than the
+ * compiled version then the table schema is upgraded but the data isn't,
+ * that's the engine's responsibility when the object is loaded. If the
+ * version is greater than the compiled version then nothing is touched.
+ * @param be The GncSqlBackend containing the database connection.
*/
- gboolean (*write) (GncSqlBackend* be);
-} GncSqlObjectBackend;
-#define GNC_SQL_BACKEND "gnc:sql:1"
-#define GNC_SQL_BACKEND_VERSION 1
+ virtual void create_tables (GncSqlBackend*);
+ /**
+ * UPDATE/INSERT a single instance of m_type_name into the database.
+ * @param be The GncSqlBackend containing the database.
+ * @param inst The QofInstance to be written out.
+ */
+ virtual bool commit (GncSqlBackend* be, QofInstance* inst);
+ /**
+ * Write all objects of m_type_name to the database.
+ * @param be The GncSqlBackend containing the database.
+ * @return true if the objects were successfully written, false otherwise.
+ */
+ virtual bool write (GncSqlBackend*) { return true; }
+ /**
+ * Return the m_type_name for the class. This value is created at
+ * compilation time and is called QofIdType or QofIdTypeConst in other parts
+ * of GnuCash. Most values are defined in src/engine/gnc-engine.h.
+ * @return m_type_name.
+ */
+ const char* type () const noexcept { return m_type_name.c_str(); }
+ /**
+ * Compare a version with the compiled version (m_version).
+ * @return true if they match.
+ */
+ const bool is_version (int version) const noexcept {
+ return version == m_version;
+ }
+protected:
+ const std::string m_table_name;
+ const int m_version;
+ const std::string m_type_name; /// The front-end QofIdType
+ const EntryVec& m_col_table; /// The ORM table definition.
+};
+
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();
+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* b, bool o, GncSqlObjectBackendPtr e) :
+ be{b}, 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;
+};
/**
* Basic column type
@@ -959,12 +1008,6 @@ gpointer gnc_sql_compile_query (QofBackend* pBEnd, QofQuery* pQuery);
void gnc_sql_free_query (QofBackend* pBEnd, gpointer pQuery);
void gnc_sql_run_query (QofBackend* pBEnd, gpointer pQuery);
-typedef struct
-{
- GncSqlBackend* be;
- gboolean is_ok;
-} write_objects_t;
-
template <typename T> T
GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
const gpointer pObject) const
diff --git a/src/backend/sql/gnc-bill-term-sql.cpp b/src/backend/sql/gnc-bill-term-sql.cpp
index 718fec1..af06bd2 100644
--- a/src/backend/sql/gnc-bill-term-sql.cpp
+++ b/src/backend/sql/gnc-bill-term-sql.cpp
@@ -95,6 +95,17 @@ 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;
+};
+
typedef struct
{
GncBillTerm* billterm;
@@ -221,8 +232,8 @@ load_single_billterm (GncSqlBackend* be, GncSqlRow& row,
return pBillTerm;
}
-static void
-load_all_billterms (GncSqlBackend* be)
+void
+GncSqlBillTermBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
@@ -278,7 +289,8 @@ load_all_billterms (GncSqlBackend* be)
typedef struct
{
GncSqlBackend* be;
- gboolean is_ok;
+ GncSqlBillTermBackend* btbe;
+ bool is_ok;
} write_billterms_t;
static void
@@ -288,26 +300,24 @@ do_save_billterm (QofInstance* inst, gpointer p2)
if (data->is_ok)
{
- data->is_ok = gnc_sql_save_billterm (data->be, inst);
+ data->is_ok = data->btbe->commit (data->be, inst);
}
}
-static gboolean
-write_billterms (GncSqlBackend* be)
+bool
+GncSqlBillTermBackend::write (GncSqlBackend* be)
{
- write_billterms_t data;
+ write_billterms_t data {be, this, true};
g_return_val_if_fail (be != NULL, FALSE);
- data.be = be;
- data.is_ok = TRUE;
qof_object_foreach (GNC_ID_BILLTERM, be->book, do_save_billterm, &data);
return data.is_ok;
}
/* ================================================================= */
-static void
-create_billterm_tables (GncSqlBackend* be)
+void
+GncSqlBillTermBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -330,18 +340,6 @@ create_billterm_tables (GncSqlBackend* be)
}
/* ================================================================= */
-gboolean
-gnc_sql_save_billterm (GncSqlBackend* be, QofInstance* inst)
-{
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (GNC_IS_BILLTERM (inst), FALSE);
- g_return_val_if_fail (be != NULL, FALSE);
-
- return gnc_sql_commit_standard_item (be, inst, TABLE_NAME, GNC_ID_BILLTERM,
- col_table);
-}
-
-/* ================================================================= */
template<> void
GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::load (const GncSqlBackend* be,
@@ -374,17 +372,8 @@ GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::add_to_query(const GncSqlBackend* be
void
gnc_billterm_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_BILLTERM,
- gnc_sql_save_billterm, /* commit */
- load_all_billterms, /* initial_load */
- create_billterm_tables, /* create_tables */
- NULL, NULL, NULL,
- write_billterms /* write */
- };
-
+ static GncSqlBillTermBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_BILLTERM, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-bill-term-sql.h b/src/backend/sql/gnc-bill-term-sql.h
index 442e1cf..af6cced 100644
--- a/src/backend/sql/gnc-bill-term-sql.h
+++ b/src/backend/sql/gnc-bill-term-sql.h
@@ -36,6 +36,5 @@ extern "C"
#include "qof.h"
}
void gnc_billterm_sql_initialize (void);
-gboolean gnc_sql_save_billterm (GncSqlBackend* be, QofInstance* inst);
#endif /* GNC_BILLTERM_SQL_H */
diff --git a/src/backend/sql/gnc-book-sql.cpp b/src/backend/sql/gnc-book-sql.cpp
index ea30076..2145172 100644
--- a/src/backend/sql/gnc-book-sql.cpp
+++ b/src/backend/sql/gnc-book-sql.cpp
@@ -68,6 +68,15 @@ 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;
+};
+
/* ================================================================= */
static gpointer
get_root_account_guid (gpointer pObject)
@@ -157,8 +166,8 @@ load_single_book (GncSqlBackend* be, GncSqlRow& row)
qof_instance_mark_clean (QOF_INSTANCE (pBook));
}
-static void
-load_all_books (GncSqlBackend* be)
+void
+GncSqlBookBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
@@ -177,7 +186,7 @@ load_all_books (GncSqlBackend* be)
if (row == result->end())
{
be->loading = FALSE;
- (void)gnc_sql_save_book (be, QOF_INSTANCE (be->book));
+ commit(be, QOF_INSTANCE (be->book));
be->loading = TRUE;
}
else
@@ -189,53 +198,11 @@ load_all_books (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_book_tables (GncSqlBackend* be)
-{
- gint version;
-
- g_return_if_fail (be != NULL);
-
- version = gnc_sql_get_table_version (be, BOOK_TABLE);
- if (version == 0)
- {
- (void)gnc_sql_create_table (be, BOOK_TABLE, TABLE_VERSION, col_table);
- }
-}
-
-/* ================================================================= */
-gboolean
-gnc_sql_save_book (GncSqlBackend* be, QofInstance* inst)
-{
- gboolean status;
-
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (QOF_IS_BOOK (inst), FALSE);
-
- status = gnc_sql_commit_standard_item (be, inst, BOOK_TABLE, GNC_ID_BOOK,
- col_table);
-
- return status;
-}
-
-/* ================================================================= */
void
gnc_sql_init_book_handler (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_BOOK,
- gnc_sql_save_book, /* commit */
- load_all_books, /* initial_load */
- create_book_tables, /* create_tables */
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
- NULL /* write */
- };
-
+ static GncSqlBookBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_BOOK, BOOK_TABLE, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-book-sql.h b/src/backend/sql/gnc-book-sql.h
index 5a5c1f7..b1afb3e 100644
--- a/src/backend/sql/gnc-book-sql.h
+++ b/src/backend/sql/gnc-book-sql.h
@@ -35,6 +35,5 @@ extern "C"
#include "qof.h"
}
void gnc_sql_init_book_handler (void);
-gboolean gnc_sql_save_book (GncSqlBackend* be, QofInstance* inst);
#endif /* GNC_BOOK_SQL_H */
diff --git a/src/backend/sql/gnc-budget-sql.cpp b/src/backend/sql/gnc-budget-sql.cpp
index 2318513..beb87c2 100644
--- a/src/backend/sql/gnc-budget-sql.cpp
+++ b/src/backend/sql/gnc-budget-sql.cpp
@@ -76,6 +76,20 @@ 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* be, QofInstance* inst) override;
+ bool write(GncSqlBackend*) override;
+private:
+ static void save(QofInstance*, void*);
+};
+
typedef struct
{
GncBudget* budget;
@@ -318,8 +332,8 @@ load_single_budget (GncSqlBackend* be, GncSqlRow& row)
return pBudget;
}
-static void
-load_all_budgets (GncSqlBackend* be)
+void
+GncSqlBudgetBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
GList* list = NULL;
@@ -349,8 +363,8 @@ load_all_budgets (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_budget_tables (GncSqlBackend* be)
+void
+GncSqlBudgetBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -371,8 +385,8 @@ create_budget_tables (GncSqlBackend* be)
}
/* ================================================================= */
-static gboolean
-save_budget (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlBudgetBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
GncBudget* pBudget = GNC_BUDGET (inst);
const GncGUID* guid;
@@ -435,18 +449,18 @@ save_budget (GncSqlBackend* be, QofInstance* inst)
}
static void
-do_save_budget (QofInstance* inst, gpointer data)
+do_save (QofInstance* inst, gpointer data)
{
write_objects_t* s = (write_objects_t*)data;
if (s->is_ok)
{
- s->is_ok = save_budget (s->be, inst);
+ s->is_ok = s->obe->commit (s->be, inst);
}
}
-static gboolean
-write_budgets (GncSqlBackend* be)
+bool
+GncSqlBudgetBackend::write (GncSqlBackend* be)
{
write_objects_t data;
@@ -454,8 +468,9 @@ write_budgets (GncSqlBackend* be)
data.be = be;
data.is_ok = TRUE;
+ data.obe = this;
qof_collection_foreach (qof_book_get_collection (be->book, GNC_ID_BUDGET),
- (QofInstanceForeachCB)do_save_budget, &data);
+ (QofInstanceForeachCB)do_save, &data);
return data.is_ok;
}
@@ -492,19 +507,8 @@ GncSqlColumnTableEntryImpl<CT_BUDGETREF>::add_to_query(const GncSqlBackend* be,
void
gnc_sql_init_budget_handler (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_BUDGET,
- save_budget, /* commit */
- load_all_budgets, /* initial_load */
- create_budget_tables, /* create_tables */
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
- write_budgets /* write */
- };
-
+ static GncSqlBudgetBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_BUDGET, BUDGET_TABLE, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-commodity-sql.cpp b/src/backend/sql/gnc-commodity-sql.cpp
index 82c2972..a77090d 100644
--- a/src/backend/sql/gnc-commodity-sql.cpp
+++ b/src/backend/sql/gnc-commodity-sql.cpp
@@ -84,6 +84,16 @@ 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;
+};
+
/* ================================================================= */
static gpointer
@@ -130,8 +140,8 @@ load_single_commodity (GncSqlBackend* be, GncSqlRow& row)
return pCommodity;
}
-static void
-load_all_commodities (GncSqlBackend* be)
+void
+GncSqlCommodityBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
gnc_commodity_table* pTable;
@@ -164,21 +174,6 @@ load_all_commodities (GncSqlBackend* be)
}
}
/* ================================================================= */
-static void
-create_commodities_tables (GncSqlBackend* be)
-{
- gint version;
-
- g_return_if_fail (be != NULL);
-
- version = gnc_sql_get_table_version (be, COMMODITIES_TABLE);
- if (version == 0)
- {
- (void)gnc_sql_create_table (be, COMMODITIES_TABLE, TABLE_VERSION, col_table);
- }
-}
-
-/* ================================================================= */
static gboolean
do_commit_commodity (GncSqlBackend* be, QofInstance* inst,
gboolean force_insert)
@@ -221,8 +216,8 @@ do_commit_commodity (GncSqlBackend* be, QofInstance* inst,
return is_ok;
}
-static gboolean
-commit_commodity (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlCommodityBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
g_return_val_if_fail (be != NULL, FALSE);
g_return_val_if_fail (inst != NULL, FALSE);
@@ -298,19 +293,9 @@ GncSqlColumnTableEntryImpl<CT_COMMODITYREF>::add_to_query(const GncSqlBackend* b
void
gnc_sql_init_commodity_handler (void)
{
- static GncSqlObjectBackend be_data =
+ static GncSqlCommodityBackend be_data =
{
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_COMMODITY,
- commit_commodity, /* commit */
- load_all_commodities, /* initial_load */
- create_commodities_tables, /* create_tables */
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
- NULL /* write */
- };
-
+ GNC_SQL_BACKEND_VERSION, GNC_ID_COMMODITY, COMMODITIES_TABLE, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-customer-sql.cpp b/src/backend/sql/gnc-customer-sql.cpp
index 583629f..c8b8c6a 100644
--- a/src/backend/sql/gnc-customer-sql.cpp
+++ b/src/backend/sql/gnc-customer-sql.cpp
@@ -90,6 +90,17 @@ 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;
+};
+
static GncCustomer*
load_single_customer (GncSqlBackend* be, GncSqlRow& row)
{
@@ -110,8 +121,8 @@ load_single_customer (GncSqlBackend* be, GncSqlRow& row)
return pCustomer;
}
-static void
-load_all_customers (GncSqlBackend* be)
+void
+GncSqlCustomerBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
@@ -140,8 +151,8 @@ load_all_customers (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_customer_tables (GncSqlBackend* be)
+void
+GncSqlCustomerBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -165,24 +176,6 @@ create_customer_tables (GncSqlBackend* be)
/* ================================================================= */
static gboolean
-save_customer (GncSqlBackend* be, QofInstance* inst)
-{
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (GNC_CUSTOMER (inst), FALSE);
- g_return_val_if_fail (be != NULL, FALSE);
-
- return gnc_sql_commit_standard_item (be, inst, TABLE_NAME, GNC_ID_CUSTOMER,
- col_table);
-}
-
-/* ================================================================= */
-typedef struct
-{
- GncSqlBackend* be;
- gboolean is_ok;
-} write_customers_t;
-
-static gboolean
customer_should_be_saved (GncCustomer* customer)
{
const char* id;
@@ -202,7 +195,7 @@ customer_should_be_saved (GncCustomer* customer)
static void
write_single_customer (QofInstance* term_p, gpointer data_p)
{
- write_customers_t* data = (write_customers_t*)data_p;
+ auto data = reinterpret_cast<write_objects_t*>(data_p);
g_return_if_fail (term_p != NULL);
g_return_if_fail (GNC_IS_CUSTOMER (term_p));
@@ -210,19 +203,20 @@ write_single_customer (QofInstance* term_p, gpointer data_p)
if (customer_should_be_saved (GNC_CUSTOMER (term_p)) && data->is_ok)
{
- data->is_ok = save_customer (data->be, term_p);
+ data->is_ok = data->obe->commit (data->be, term_p);
}
}
-static gboolean
-write_customers (GncSqlBackend* be)
+bool
+GncSqlCustomerBackend::write (GncSqlBackend* be)
{
- write_customers_t data;
+ write_objects_t data;
g_return_val_if_fail (be != NULL, FALSE);
data.be = be;
data.is_ok = TRUE;
+ data.obe = this;
qof_object_foreach (GNC_ID_CUSTOMER, be->book, write_single_customer,
(gpointer)&data);
return data.is_ok;
@@ -232,17 +226,8 @@ write_customers (GncSqlBackend* be)
void
gnc_customer_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_CUSTOMER,
- save_customer, /* commit */
- load_all_customers, /* initial_load */
- create_customer_tables, /* create_tables */
- NULL, NULL, NULL,
- write_customers /* write */
- };
-
+ static GncSqlCustomerBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_CUSTOMER, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-employee-sql.cpp b/src/backend/sql/gnc-employee-sql.cpp
index 20e2df7..b66ba07 100644
--- a/src/backend/sql/gnc-employee-sql.cpp
+++ b/src/backend/sql/gnc-employee-sql.cpp
@@ -75,6 +75,18 @@ 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;
+};
+
static GncEmployee*
load_single_employee (GncSqlBackend* be, GncSqlRow& row)
{
@@ -95,8 +107,8 @@ load_single_employee (GncSqlBackend* be, GncSqlRow& row)
return pEmployee;
}
-static void
-load_all_employees (GncSqlBackend* be)
+void
+GncSqlEmployeeBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
@@ -126,8 +138,8 @@ load_all_employees (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_employee_tables (GncSqlBackend* be)
+void
+GncSqlEmployeeBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -150,8 +162,8 @@ create_employee_tables (GncSqlBackend* be)
}
/* ================================================================= */
-static gboolean
-save_employee (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlEmployeeBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
GncEmployee* emp;
const GncGUID* guid;
@@ -236,12 +248,12 @@ write_single_employee (QofInstance* term_p, gpointer data_p)
if (s->is_ok && employee_should_be_saved (GNC_EMPLOYEE (term_p)))
{
- s->is_ok = save_employee (s->be, term_p);
+ s->is_ok = s->obe->commit (s->be, term_p);
}
}
-static gboolean
-write_employees (GncSqlBackend* be)
+bool
+GncSqlEmployeeBackend::write (GncSqlBackend* be)
{
write_objects_t data;
@@ -249,6 +261,7 @@ write_employees (GncSqlBackend* be)
data.be = be;
data.is_ok = TRUE;
+ data.obe = this;
qof_object_foreach (GNC_ID_EMPLOYEE, be->book, write_single_employee, &data);
return data.is_ok;
@@ -258,17 +271,8 @@ write_employees (GncSqlBackend* be)
void
gnc_employee_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_EMPLOYEE,
- save_employee, /* commit */
- load_all_employees, /* initial_load */
- create_employee_tables, /* create_tables */
- NULL, NULL, NULL,
- write_employees /* write */
- };
-
+ static GncSqlEmployeeBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_EMPLOYEE, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-entry-sql.cpp b/src/backend/sql/gnc-entry-sql.cpp
index 59b6bf8..75195df 100644
--- a/src/backend/sql/gnc-entry-sql.cpp
+++ b/src/backend/sql/gnc-entry-sql.cpp
@@ -124,6 +124,17 @@ 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;
+};
+
static void
entry_set_invoice (gpointer pObject, gpointer val)
{
@@ -178,8 +189,8 @@ load_single_entry (GncSqlBackend* be, GncSqlRow& row)
return pEntry;
}
-static void
-load_all_entries (GncSqlBackend* be)
+void
+GncSqlEntryBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
@@ -207,8 +218,8 @@ load_all_entries (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_entry_tables (GncSqlBackend* be)
+void
+GncSqlEntryBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -234,18 +245,6 @@ create_entry_tables (GncSqlBackend* be)
}
/* ================================================================= */
-static gboolean
-save_entry (GncSqlBackend* be, QofInstance* inst)
-{
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (GNC_IS_ENTRY (inst), FALSE);
- g_return_val_if_fail (be != NULL, FALSE);
-
- return gnc_sql_commit_standard_item (be, inst, TABLE_NAME, GNC_ID_ENTRY,
- col_table);
-}
-
-/* ================================================================= */
static void
write_single_entry (QofInstance* term_p, gpointer data_p)
{
@@ -261,19 +260,16 @@ write_single_entry (QofInstance* term_p, gpointer data_p)
gncEntryGetInvoice (entry) != NULL ||
gncEntryGetBill (entry) != NULL))
{
- s->is_ok = save_entry (s->be, term_p);
+ s->commit (term_p);
}
}
-static gboolean
-write_entries (GncSqlBackend* be)
+bool
+GncSqlEntryBackend::write (GncSqlBackend* be)
{
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data{be, true, this};
- data.be = be;
- data.is_ok = TRUE;
qof_object_foreach (GNC_ID_ENTRY, be->book, write_single_entry, &data);
return data.is_ok;
@@ -283,17 +279,8 @@ write_entries (GncSqlBackend* be)
void
gnc_entry_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_ENTRY,
- save_entry, /* commit */
- load_all_entries, /* initial_load */
- create_entry_tables, /* create_tables */
- NULL, NULL, NULL,
- write_entries /* write */
- };
-
+ static GncSqlEntryBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_ENTRY, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-invoice-sql.cpp b/src/backend/sql/gnc-invoice-sql.cpp
index fd8450d..71eb593 100644
--- a/src/backend/sql/gnc-invoice-sql.cpp
+++ b/src/backend/sql/gnc-invoice-sql.cpp
@@ -96,6 +96,18 @@ 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* be, QofInstance* inst) override;
+ bool write(GncSqlBackend*) override;
+};
+
static GncInvoice*
load_single_invoice (GncSqlBackend* be, GncSqlRow& row)
{
@@ -116,8 +128,8 @@ load_single_invoice (GncSqlBackend* be, GncSqlRow& row)
return pInvoice;
}
-static void
-load_all_invoices (GncSqlBackend* be)
+void
+GncSqlInvoiceBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
@@ -145,8 +157,8 @@ load_all_invoices (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_invoice_tables (GncSqlBackend* be)
+void
+GncSqlInvoiceBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -172,8 +184,8 @@ create_invoice_tables (GncSqlBackend* be)
}
/* ================================================================= */
-static gboolean
-save_invoice (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlInvoiceBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
const GncGUID* guid;
GncInvoice* invoice;
@@ -250,7 +262,7 @@ invoice_should_be_saved (GncInvoice* invoice)
static void
write_single_invoice (QofInstance* term_p, gpointer data_p)
{
- write_objects_t* s = (write_objects_t*)data_p;
+ auto s = reinterpret_cast<write_objects_t*>(data_p);
g_return_if_fail (term_p != NULL);
g_return_if_fail (GNC_IS_INVOICE (term_p));
@@ -258,19 +270,16 @@ write_single_invoice (QofInstance* term_p, gpointer data_p)
if (s->is_ok && invoice_should_be_saved (GNC_INVOICE (term_p)))
{
- s->is_ok = save_invoice (s->be, term_p);
+ s->commit (term_p);
}
}
-static gboolean
-write_invoices (GncSqlBackend* be)
+bool
+GncSqlInvoiceBackend::write (GncSqlBackend* be)
{
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data{be, true, this};
- data.be = be;
- data.is_ok = TRUE;
qof_object_foreach (GNC_ID_INVOICE, be->book, write_single_invoice, &data);
return data.is_ok;
@@ -309,17 +318,8 @@ GncSqlColumnTableEntryImpl<CT_INVOICEREF>::add_to_query(const GncSqlBackend* be,
void
gnc_invoice_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_INVOICE,
- save_invoice, /* commit */
- load_all_invoices, /* initial_load */
- create_invoice_tables, /* create_tables */
- NULL, NULL, NULL,
- write_invoices /* write */
- };
-
+ static GncSqlInvoiceBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_INVOICE, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-job-sql.cpp b/src/backend/sql/gnc-job-sql.cpp
index b57a867..e7992e4 100644
--- a/src/backend/sql/gnc-job-sql.cpp
+++ b/src/backend/sql/gnc-job-sql.cpp
@@ -69,6 +69,17 @@ 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;
+};
+
+
static GncJob*
load_single_job (GncSqlBackend* be, GncSqlRow& row)
{
@@ -89,8 +100,8 @@ load_single_job (GncSqlBackend* be, GncSqlRow& row)
return pJob;
}
-static void
-load_all_jobs (GncSqlBackend* be)
+void
+GncSqlJobBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
@@ -117,33 +128,6 @@ load_all_jobs (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_job_tables (GncSqlBackend* be)
-{
- gint version;
-
- g_return_if_fail (be != NULL);
-
- version = gnc_sql_get_table_version (be, TABLE_NAME);
- if (version == 0)
- {
- gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
- }
-}
-
-/* ================================================================= */
-static gboolean
-save_job (GncSqlBackend* be, QofInstance* inst)
-{
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (GNC_IS_JOB (inst), FALSE);
- g_return_val_if_fail (be != NULL, FALSE);
-
- return gnc_sql_commit_standard_item (be, inst, TABLE_NAME, GNC_ID_JOB,
- col_table);
-}
-
-/* ================================================================= */
static gboolean
job_should_be_saved (GncJob* job)
{
@@ -164,7 +148,7 @@ job_should_be_saved (GncJob* job)
static void
write_single_job (QofInstance* term_p, gpointer data_p)
{
- write_objects_t* s = (write_objects_t*)data_p;
+ auto s = reinterpret_cast<write_objects_t*>(data_p);
g_return_if_fail (term_p != NULL);
g_return_if_fail (GNC_IS_JOB (term_p));
@@ -172,19 +156,16 @@ write_single_job (QofInstance* term_p, gpointer data_p)
if (s->is_ok && job_should_be_saved (GNC_JOB (term_p)))
{
- s->is_ok = save_job (s->be, term_p);
+ s->commit (term_p);
}
}
-static gboolean
-write_jobs (GncSqlBackend* be)
+bool
+GncSqlJobBackend::write (GncSqlBackend* be)
{
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data{be, true, this};
- data.be = be;
- data.is_ok = TRUE;
qof_object_foreach (GNC_ID_JOB, be->book, write_single_job, &data);
return data.is_ok;
@@ -194,17 +175,8 @@ write_jobs (GncSqlBackend* be)
void
gnc_job_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_JOB,
- save_job, /* commit */
- load_all_jobs, /* initial_load */
- create_job_tables, /* create_tables */
- NULL, NULL, NULL,
- write_jobs /* write */
- };
-
+ static GncSqlJobBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_JOB, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-lots-sql.cpp b/src/backend/sql/gnc-lots-sql.cpp
index 42dfd9e..5693459 100644
--- a/src/backend/sql/gnc-lots-sql.cpp
+++ b/src/backend/sql/gnc-lots-sql.cpp
@@ -63,6 +63,17 @@ 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;
+};
+
/* ================================================================= */
static gpointer
get_lot_account (gpointer pObject)
@@ -111,8 +122,8 @@ load_single_lot (GncSqlBackend* be, GncSqlRow& row)
return lot;
}
-static void
-load_all_lots (GncSqlBackend* be)
+void
+GncSqlLotsBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
@@ -135,8 +146,8 @@ load_all_lots (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_lots_tables (GncSqlBackend* be)
+void
+GncSqlLotsBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -163,39 +174,23 @@ create_lots_tables (GncSqlBackend* be)
}
}
-/* ================================================================= */
-
-static gboolean
-commit_lot (GncSqlBackend* be, QofInstance* inst)
-{
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (GNC_IS_LOT (inst), FALSE);
-
- return gnc_sql_commit_standard_item (be, inst, TABLE_NAME, GNC_ID_LOT,
- col_table);
-}
-
static void
do_save_lot (QofInstance* inst, gpointer data)
{
- write_objects_t* s = (write_objects_t*)data;
+ auto s = reinterpret_cast<write_objects_t*>(data);
if (s->is_ok)
{
- s->is_ok = commit_lot (s->be, inst);
+ s->commit (inst);
}
}
-static gboolean
-write_lots (GncSqlBackend* be)
+bool
+GncSqlLotsBackend::write (GncSqlBackend* be)
{
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data{be, true, this};
- data.be = be;
- data.is_ok = TRUE;
qof_collection_foreach (qof_book_get_collection (be->book, GNC_ID_LOT),
(QofInstanceForeachCB)do_save_lot, &data);
return data.is_ok;
@@ -233,17 +228,8 @@ GncSqlColumnTableEntryImpl<CT_LOTREF>::add_to_query(const GncSqlBackend* be,
void
gnc_sql_init_lot_handler (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_LOT,
- commit_lot, /* commit */
- load_all_lots, /* initial_load */
- create_lots_tables, /* create tables */
- NULL, NULL, NULL,
- write_lots /* save all */
- };
-
+ static GncSqlLotsBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_LOT, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
diff --git a/src/backend/sql/gnc-order-sql.cpp b/src/backend/sql/gnc-order-sql.cpp
index d931eb7..57f6954 100644
--- a/src/backend/sql/gnc-order-sql.cpp
+++ b/src/backend/sql/gnc-order-sql.cpp
@@ -70,6 +70,16 @@ 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;
+};
+
static GncOrder*
load_single_order (GncSqlBackend* be, GncSqlRow& row)
{
@@ -90,8 +100,8 @@ load_single_order (GncSqlBackend* be, GncSqlRow& row)
return pOrder;
}
-static void
-load_all_orders (GncSqlBackend* be)
+void
+GncSqlOrderBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
g_return_if_fail (be != NULL);
@@ -118,33 +128,6 @@ load_all_orders (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_order_tables (GncSqlBackend* be)
-{
- gint version;
-
- g_return_if_fail (be != NULL);
-
- version = gnc_sql_get_table_version (be, TABLE_NAME);
- if (version == 0)
- {
- gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
- }
-}
-
-/* ================================================================= */
-static gboolean
-save_order (GncSqlBackend* be, QofInstance* inst)
-{
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (GNC_IS_ORDER (inst), FALSE);
- g_return_val_if_fail (be != NULL, FALSE);
-
- return gnc_sql_commit_standard_item (be, inst, TABLE_NAME, GNC_ID_ORDER,
- col_table);
-}
-
-/* ================================================================= */
static gboolean
order_should_be_saved (GncOrder* order)
{
@@ -165,7 +148,7 @@ order_should_be_saved (GncOrder* order)
static void
write_single_order (QofInstance* term_p, gpointer data_p)
{
- write_objects_t* s = (write_objects_t*)data_p;
+ auto s = reinterpret_cast<write_objects_t*>(data_p);
g_return_if_fail (term_p != NULL);
g_return_if_fail (GNC_IS_ORDER (term_p));
@@ -173,19 +156,16 @@ write_single_order (QofInstance* term_p, gpointer data_p)
if (s->is_ok && order_should_be_saved (GNC_ORDER (term_p)))
{
- s->is_ok = save_order (s->be, term_p);
+ s->commit (term_p);
}
}
-static gboolean
-write_orders (GncSqlBackend* be)
+bool
+GncSqlOrderBackend::write (GncSqlBackend* be)
{
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data{be, true, this};
- data.be = be;
- data.is_ok = TRUE;
qof_object_foreach (GNC_ID_ORDER, be->book, write_single_order, &data);
return data.is_ok;
@@ -223,16 +203,8 @@ GncSqlColumnTableEntryImpl<CT_ORDERREF>::add_to_query(const GncSqlBackend* be,
void
gnc_order_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_ORDER,
- save_order, /* commit */
- load_all_orders, /* initial_load */
- create_order_tables, /* create_tables */
- NULL, NULL, NULL,
- write_orders /* write */
- };
+ static GncSqlOrderBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_ORDER, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
diff --git a/src/backend/sql/gnc-price-sql.cpp b/src/backend/sql/gnc-price-sql.cpp
index bea1c51..f3c2f4e 100644
--- a/src/backend/sql/gnc-price-sql.cpp
+++ b/src/backend/sql/gnc-price-sql.cpp
@@ -67,6 +67,19 @@ 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* be, QofInstance* inst) override;
+ bool write(GncSqlBackend*) override;
+};
+
+
/* ================================================================= */
static GNCPrice*
@@ -85,8 +98,8 @@ load_single_price (GncSqlBackend* be, GncSqlRow& row)
return pPrice;
}
-static void
-load_all_prices (GncSqlBackend* be)
+void
+GncSqlPriceBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
QofBook* pBook;
@@ -103,7 +116,7 @@ load_all_prices (GncSqlBackend* be)
delete stmt;
if (result->begin() == result->end())
return;
-
+
GNCPrice* pPrice;
gchar* sql;
@@ -127,8 +140,8 @@ load_all_prices (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_prices_tables (GncSqlBackend* be)
+void
+GncSqlPriceBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -151,8 +164,8 @@ create_prices_tables (GncSqlBackend* be)
/* ================================================================= */
-static gboolean
-save_price (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlPriceBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
GNCPrice* pPrice = GNC_PRICE (inst);
E_DB_OPERATION op;
@@ -193,34 +206,29 @@ save_price (GncSqlBackend* be, QofInstance* inst)
return is_ok;
}
-static gboolean
+gboolean
write_price (GNCPrice* p, gpointer data)
{
- write_objects_t* s = (write_objects_t*)data;
+ auto s = reinterpret_cast<write_objects_t*>(data);
g_return_val_if_fail (p != NULL, FALSE);
g_return_val_if_fail (data != NULL, FALSE);
if (s->is_ok && gnc_price_get_source (p) != PRICE_SOURCE_TEMP)
{
- s->is_ok = save_price (s->be, QOF_INSTANCE (p));
+ s->commit (QOF_INSTANCE(p));
}
return s->is_ok;
}
-static gboolean
-write_prices (GncSqlBackend* be)
+bool
+GncSqlPriceBackend::write (GncSqlBackend* be)
{
- GNCPriceDB* priceDB;
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data{be, true, this};
- priceDB = gnc_pricedb_get_db (be->book);
-
- data.be = be;
- data.is_ok = TRUE;
+ auto priceDB = gnc_pricedb_get_db (be->book);
return gnc_pricedb_foreach_price (priceDB, write_price, &data, TRUE);
}
@@ -228,17 +236,8 @@ write_prices (GncSqlBackend* be)
void
gnc_sql_init_price_handler (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_PRICE,
- save_price, /* commit */
- load_all_prices, /* initial_load */
- create_prices_tables, /* create tables */
- NULL, NULL, NULL,
- write_prices /* write */
- };
-
+ static GncSqlPriceBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_PRICE, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
diff --git a/src/backend/sql/gnc-recurrence-sql.cpp b/src/backend/sql/gnc-recurrence-sql.cpp
index c56f560..44a1675 100644
--- a/src/backend/sql/gnc-recurrence-sql.cpp
+++ b/src/backend/sql/gnc-recurrence-sql.cpp
@@ -109,6 +109,21 @@ static const EntryVec weekend_adjust_col_table
"recurrence_weekend_adjust", BUDGET_MAX_RECURRENCE_WEEKEND_ADJUST_LEN, 0)
});
+/**
+ * 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; }
+};
+
/* ================================================================= */
static gpointer
@@ -389,8 +404,8 @@ upgrade_recurrence_table_1_2 (GncSqlBackend* be)
}
-static void
-create_recurrence_tables (GncSqlBackend* be)
+void
+GncSqlRecurrenceBackend::create_tables (GncSqlBackend* be)
{
gint version;
gboolean ok;
@@ -421,19 +436,8 @@ create_recurrence_tables (GncSqlBackend* be)
void
gnc_sql_init_recurrence_handler (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_ACCOUNT,
- NULL, /* commit - cannot occur */
- NULL, /* initial_load - cannot occur */
- create_recurrence_tables, /* create_tables */
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
- NULL /* write */
- };
-
+ static GncSqlRecurrenceBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_ACCOUNT, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-schedxaction-sql.cpp b/src/backend/sql/gnc-schedxaction-sql.cpp
index 0f2fe6f..857507a 100644
--- a/src/backend/sql/gnc-schedxaction-sql.cpp
+++ b/src/backend/sql/gnc-schedxaction-sql.cpp
@@ -81,6 +81,16 @@ 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* be, QofInstance* inst) override;
+};
+
/* ================================================================= */
static SchedXaction*
load_single_sx (GncSqlBackend* be, GncSqlRow& row)
@@ -108,8 +118,8 @@ load_single_sx (GncSqlBackend* be, GncSqlRow& row)
return pSx;
}
-static void
-load_all_sxes (GncSqlBackend* be)
+void
+GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt = NULL;
@@ -142,24 +152,10 @@ load_all_sxes (GncSqlBackend* be)
}
}
-/* ================================================================= */
-static void
-create_sx_tables (GncSqlBackend* be)
-{
- gint version;
-
- g_return_if_fail (be != NULL);
-
- version = gnc_sql_get_table_version (be, SCHEDXACTION_TABLE);
- if (version == 0)
- {
- (void)gnc_sql_create_table (be, SCHEDXACTION_TABLE, TABLE_VERSION, col_table);
- }
-}
/* ================================================================= */
-gboolean
-gnc_sql_save_schedxaction (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlSchedXactionBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
SchedXaction* pSx;
const GncGUID* guid;
@@ -218,19 +214,9 @@ gnc_sql_save_schedxaction (GncSqlBackend* be, QofInstance* inst)
void
gnc_sql_init_schedxaction_handler (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_SCHEDXACTION,
- gnc_sql_save_schedxaction, /* commit */
- load_all_sxes, /* initial_load */
- create_sx_tables, /* create_tables */
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
- NULL /* write */
- };
-
+ static GncSqlSchedXactionBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_SCHEDXACTION, SCHEDXACTION_TABLE,
+ col_table};
gnc_sql_register_backend(&be_data);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index e6b159e..2a682a9 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -160,6 +160,21 @@ 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; }
+};
+
/* ================================================================= */
static gchar*
@@ -994,8 +1009,8 @@ void gnc_sql_slots_load_for_sql_subquery (GncSqlBackend* be,
}
/* ================================================================= */
-static void
-create_slots_tables (GncSqlBackend* be)
+void
+GncSqlSlotsBackend::create_tables (GncSqlBackend* be)
{
gint version;
gboolean ok;
@@ -1048,23 +1063,8 @@ create_slots_tables (GncSqlBackend* be)
void
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 */
- create_slots_tables, /* create_tables */
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
- NULL /* write */
- };
-
+ 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));
}
diff --git a/src/backend/sql/gnc-tax-table-sql.cpp b/src/backend/sql/gnc-tax-table-sql.cpp
index 577eef0..f336ef2 100644
--- a/src/backend/sql/gnc-tax-table-sql.cpp
+++ b/src/backend/sql/gnc-tax-table-sql.cpp
@@ -113,6 +113,18 @@ 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* be, QofInstance* inst) override;
+ bool write(GncSqlBackend*) override;
+};
+
typedef struct
{
GncTaxTable* tt;
@@ -278,8 +290,8 @@ load_single_taxtable (GncSqlBackend* be, GncSqlRow& row,
qof_instance_mark_clean (QOF_INSTANCE (tt));
}
-static void
-load_all_taxtables (GncSqlBackend* be)
+void
+GncSqlTaxTableBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
@@ -319,8 +331,8 @@ load_all_taxtables (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_taxtable_tables (GncSqlBackend* be)
+void
+GncSqlTaxTableBackend::create_tables (GncSqlBackend* be)
{
gint version;
@@ -396,8 +408,8 @@ save_tt_entries (GncSqlBackend* be, const GncGUID* guid, GList* entries)
return is_ok;
}
-static gboolean
-save_taxtable (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlTaxTableBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
GncTaxTable* tt;
const GncGUID* guid;
@@ -456,23 +468,20 @@ save_taxtable (GncSqlBackend* be, QofInstance* inst)
static void
save_next_taxtable (QofInstance* inst, gpointer data)
{
- write_objects_t* s = (write_objects_t*)data;
+ auto s = reinterpret_cast<write_objects_t*>(data);
if (s->is_ok)
{
- s->is_ok = save_taxtable (s->be, inst);
+ s->commit (inst);
}
}
-static gboolean
-write_taxtables (GncSqlBackend* be)
+bool
+GncSqlTaxTableBackend::write (GncSqlBackend* be)
{
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data{be, true, this};
- data.be = be;
- data.is_ok = TRUE;
qof_object_foreach (GNC_ID_TAXTABLE, be->book, save_next_taxtable, &data);
return data.is_ok;
@@ -511,17 +520,8 @@ GncSqlColumnTableEntryImpl<CT_TAXTABLEREF>::add_to_query(const GncSqlBackend* be
void
gnc_taxtable_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_TAXTABLE,
- save_taxtable, /* commit */
- load_all_taxtables, /* initial_load */
- create_taxtable_tables, /* create_tables */
- NULL, NULL, NULL,
- write_taxtables /* write */
- };
-
+ 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 ===================== */
diff --git a/src/backend/sql/gnc-transaction-sql.cpp b/src/backend/sql/gnc-transaction-sql.cpp
index 5baedef..d64a797 100644
--- a/src/backend/sql/gnc-transaction-sql.cpp
+++ b/src/backend/sql/gnc-transaction-sql.cpp
@@ -66,12 +66,14 @@ static QofLogModule log_module = G_LOG_DOMAIN;
#define SPLIT_TABLE "splits"
#define SPLIT_TABLE_VERSION 4
-typedef struct
+struct split_info_t : public write_objects_t
{
- GncSqlBackend* be;
+ split_info_t () = default;
+ split_info_t (GncSqlBackend* be, bool o,
+ GncSqlObjectBackendPtr e, const GncGUID* g):
+ write_objects_t(be, o, e), guid{g} {}
const GncGUID* guid;
- gboolean is_ok;
-} split_info_t;
+};
#define TX_MAX_NUM_LEN 2048
#define TX_MAX_DESCRIPTION_LEN 2048
@@ -133,6 +135,36 @@ 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* be, QofInstance* inst) override;
+};
+
+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* 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,
+ run_split_query,
+ free_split_query,
+*/
+
/* ================================================================= */
static gpointer
@@ -447,15 +479,15 @@ query_transactions (GncSqlBackend* be, GncSqlStatement* stmt)
*
* @param be SQL backend
*/
-static void
-create_transaction_tables (GncSqlBackend* be)
+void
+GncSqlTransBackend::create_tables (GncSqlBackend* be)
{
gint version;
gboolean ok;
g_return_if_fail (be != NULL);
- version = gnc_sql_get_table_version (be, TRANSACTION_TABLE);
+ version = gnc_sql_get_table_version (be, m_table_name.c_str());
if (version == 0)
{
(void)gnc_sql_create_table (be, TRANSACTION_TABLE, TX_TABLE_VERSION,
@@ -467,35 +499,35 @@ create_transaction_tables (GncSqlBackend* be)
PERR ("Unable to create index\n");
}
}
- else if (version < TX_TABLE_VERSION)
+ else if (version < m_version)
{
/* Upgrade:
1->2: 64 bit int handling
2->3: allow dates to be NULL
*/
- gnc_sql_upgrade_table (be, TRANSACTION_TABLE, tx_col_table);
- (void)gnc_sql_set_table_version (be, TRANSACTION_TABLE, TX_TABLE_VERSION);
- PINFO ("Transactions table upgraded from version %d to version %d\n", version,
- TX_TABLE_VERSION);
+ gnc_sql_upgrade_table (be, m_table_name.c_str(), tx_col_table);
+ (void)gnc_sql_set_table_version (be, m_table_name.c_str(), m_version);
+ PINFO ("Transactions table upgraded from version %d to version %d\n",
+ version, m_version);
}
+}
+void
+GncSqlSplitBackend::create_tables (GncSqlBackend* be)
+{
+ g_return_if_fail (be != nullptr);
- version = gnc_sql_get_table_version (be, SPLIT_TABLE);
+ auto version = gnc_sql_get_table_version (be, m_table_name.c_str());
if (version == 0)
{
- (void)gnc_sql_create_table (be, SPLIT_TABLE, SPLIT_TABLE_VERSION,
- split_col_table);
- ok = gnc_sql_create_index (be, "splits_tx_guid_index", SPLIT_TABLE,
- tx_guid_col_table);
- if (!ok)
- {
+ (void)gnc_sql_create_table (be, m_table_name.c_str(),
+ m_version, m_col_table);
+ if (!gnc_sql_create_index (be, "splits_tx_guid_index",
+ m_table_name.c_str(), tx_guid_col_table))
PERR ("Unable to create index\n");
- }
- ok = gnc_sql_create_index (be, "splits_account_guid_index", SPLIT_TABLE,
- account_guid_col_table);
- if (!ok)
- {
+ if (!gnc_sql_create_index (be, "splits_account_guid_index",
+ m_table_name.c_str(),
+ account_guid_col_table))
PERR ("Unable to create index\n");
- }
}
else if (version < SPLIT_TABLE_VERSION)
{
@@ -503,22 +535,18 @@ create_transaction_tables (GncSqlBackend* be)
/* Upgrade:
1->2: 64 bit int handling
3->4: Split reconcile date can be NULL */
- gnc_sql_upgrade_table (be, SPLIT_TABLE, split_col_table);
- ok = gnc_sql_create_index (be, "splits_tx_guid_index", SPLIT_TABLE,
- tx_guid_col_table);
- if (!ok)
- {
+ gnc_sql_upgrade_table (be, m_table_name.c_str(), split_col_table);
+ if (!gnc_sql_create_index (be, "splits_tx_guid_index",
+ m_table_name.c_str(),
+ tx_guid_col_table))
PERR ("Unable to create index\n");
- }
- ok = gnc_sql_create_index (be, "splits_account_guid_index", SPLIT_TABLE,
- account_guid_col_table);
- if (!ok)
- {
+ if (!gnc_sql_create_index (be, "splits_account_guid_index",
+ m_table_name.c_str(),
+ account_guid_col_table))
PERR ("Unable to create index\n");
- }
- (void)gnc_sql_set_table_version (be, SPLIT_TABLE, SPLIT_TABLE_VERSION);
+ (void)gnc_sql_set_table_version (be, m_table_name.c_str(), m_version);
PINFO ("Splits table upgraded from version %d to version %d\n", version,
- SPLIT_TABLE_VERSION);
+ m_version);
}
}
/* ================================================================= */
@@ -581,8 +609,8 @@ delete_splits (GncSqlBackend* be, Transaction* pTx)
* @param inst Split
* @return TRUE if successful, FALSE if error
*/
-static gboolean
-commit_split (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlSplitBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
E_DB_OPERATION op;
gboolean is_infant;
@@ -623,54 +651,19 @@ commit_split (GncSqlBackend* be, QofInstance* inst)
return is_ok;
}
-static void
-save_split_cb (gpointer data, gpointer user_data)
-{
- split_info_t* split_info = (split_info_t*)user_data;
- Split* pSplit = GNC_SPLIT (data);
-
- g_return_if_fail (data != NULL);
- g_return_if_fail (GNC_IS_SPLIT (data));
- g_return_if_fail (user_data != NULL);
-
- if (split_info->is_ok)
- {
- split_info->is_ok = commit_split (split_info->be, QOF_INSTANCE (pSplit));
- }
-}
-
-static gboolean
-save_splits (GncSqlBackend* be, const GncGUID* tx_guid, SplitList* pSplitList)
-{
- split_info_t split_info;
-
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (tx_guid != NULL, FALSE);
- g_return_val_if_fail (pSplitList != NULL, FALSE);
-
- split_info.be = be;
- split_info.guid = tx_guid;
- split_info.is_ok = TRUE;
- g_list_foreach (pSplitList, save_split_cb, &split_info);
- return split_info.is_ok;
-}
-
-static gboolean
-save_transaction (GncSqlBackend* be, Transaction* pTx, gboolean do_save_splits)
+bool
+GncSqlTransBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
- const GncGUID* guid;
E_DB_OPERATION op;
- gboolean is_infant;
- QofInstance* inst;
gboolean is_ok = TRUE;
const char* err = NULL;
g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (pTx != NULL, FALSE);
+ g_return_val_if_fail (inst != NULL, FALSE);
- inst = QOF_INSTANCE (pTx);
- is_infant = qof_instance_get_infant (inst);
+ auto pTx = GNC_TRANS(inst);
+ auto is_infant = qof_instance_get_infant (inst);
if (qof_instance_get_destroying (inst))
{
op = OP_DB_DELETE;
@@ -708,8 +701,8 @@ save_transaction (GncSqlBackend* be, Transaction* pTx, gboolean do_save_splits)
if (is_ok)
{
- // Commit slots and splits
- guid = qof_instance_get_guid (inst);
+ // Commit slots
+ auto guid = qof_instance_get_guid (inst);
if (!qof_instance_get_destroying (inst))
{
is_ok = gnc_sql_slots_save (be, guid, is_infant, inst);
@@ -717,14 +710,6 @@ save_transaction (GncSqlBackend* be, Transaction* pTx, gboolean do_save_splits)
{
err = "Slots save failed. Check trace log for SQL errors";
}
- if (is_ok && do_save_splits)
- {
- is_ok = save_splits (be, guid, xaccTransGetSplitList (pTx));
- if (! is_ok)
- {
- err = "Split save failed. Check trace log for SQL errors";
- }
- }
}
else
{
@@ -767,26 +752,6 @@ save_transaction (GncSqlBackend* be, Transaction* pTx, gboolean do_save_splits)
return is_ok;
}
-gboolean
-gnc_sql_save_transaction (GncSqlBackend* be, QofInstance* inst)
-{
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (GNC_IS_TRANS (inst), FALSE);
-
- return save_transaction (be, GNC_TRANS (inst), /* do_save_splits */TRUE);
-}
-
-static gboolean
-commit_transaction (GncSqlBackend* be, QofInstance* inst)
-{
- g_return_val_if_fail (be != NULL, FALSE);
- g_return_val_if_fail (inst != NULL, FALSE);
- g_return_val_if_fail (GNC_IS_TRANS (inst), FALSE);
-
- return save_transaction (be, GNC_TRANS (inst), /* do_save_splits */FALSE);
-}
-
/* ================================================================= */
/**
* Loads all transactions for an account.
@@ -825,7 +790,8 @@ void gnc_sql_transaction_load_tx_for_account (GncSqlBackend* be,
*
* @param be SQL backend
*/
-void gnc_sql_transaction_load_all_tx (GncSqlBackend* be)
+void
+GncSqlTransBackend::load_all (GncSqlBackend* be)
{
gchar* query_sql;
GncSqlStatement* stmt;
@@ -1471,41 +1437,8 @@ GncSqlColumnTableEntryImpl<CT_TXREF>::add_to_query(const GncSqlBackend* be,
void
gnc_sql_init_transaction_handler (void)
{
- static GncSqlObjectBackend be_data_tx =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_TRANS,
- commit_transaction, /* commit */
-#if LOAD_TRANSACTIONS_AS_NEEDED
- NULL, /* initial load */
-#else
- gnc_sql_transaction_load_all_tx,
-#endif
- create_transaction_tables, /* create tables */
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
- NULL /* write */
- };
- static GncSqlObjectBackend be_data_split =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_SPLIT,
- commit_split, /* commit */
- NULL, /* initial_load */
- NULL, /* create tables */
-#if LOAD_TRANSACTIONS_AS_NEEDED
- compile_split_query,
- run_split_query,
- free_split_query,
-#else
- NULL, /* compile_query */
- NULL, /* run_query */
- NULL, /* free_query */
-#endif
- NULL /* write */
- };
-
+ 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);
}
diff --git a/src/backend/sql/gnc-transaction-sql.h b/src/backend/sql/gnc-transaction-sql.h
index eae7e63..9bec050 100644
--- a/src/backend/sql/gnc-transaction-sql.h
+++ b/src/backend/sql/gnc-transaction-sql.h
@@ -39,23 +39,6 @@ extern "C"
void gnc_sql_init_transaction_handler (void);
/**
- * Commits all of the splits for a transaction.
- *
- * @param be SQL backend
- * @param pTx Transaction
- */
-void gnc_sql_transaction_commit_splits (GncSqlBackend* be, Transaction* pTx);
-
-/**
- * Saves a transaction to the db.
- *
- * @param be SQL backend
- * @param inst Transaction instance
- * @return TRUE if successful, FALSE if unsuccessful
- */
-gboolean gnc_sql_save_transaction (GncSqlBackend* be, QofInstance* inst);
-
-/**
* Loads all transactions which have splits for a specific account.
*
* @param be SQL backend
@@ -63,14 +46,6 @@ gboolean gnc_sql_save_transaction (GncSqlBackend* be, QofInstance* inst);
*/
void gnc_sql_transaction_load_tx_for_account (GncSqlBackend* be,
Account* account);
-
-/**
- * Loads all transactions.
- *
- * @param be SQL backend
- */
-void gnc_sql_transaction_load_all_tx (GncSqlBackend* be);
-
typedef struct
{
Account* acct;
diff --git a/src/backend/sql/gnc-vendor-sql.cpp b/src/backend/sql/gnc-vendor-sql.cpp
index 0caf56a..e2fe425 100644
--- a/src/backend/sql/gnc-vendor-sql.cpp
+++ b/src/backend/sql/gnc-vendor-sql.cpp
@@ -79,6 +79,17 @@ 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;
+};
+
static GncVendor*
load_single_vendor (GncSqlBackend* be, GncSqlRow& row)
{
@@ -99,8 +110,8 @@ load_single_vendor (GncSqlBackend* be, GncSqlRow& row)
return pVendor;
}
-static void
-load_all_vendors (GncSqlBackend* be)
+void
+GncSqlVendorBackend::load_all (GncSqlBackend* be)
{
GncSqlStatement* stmt;
@@ -126,23 +137,8 @@ load_all_vendors (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-create_vendor_tables (GncSqlBackend* be)
-{
- gint version;
-
- g_return_if_fail (be != NULL);
-
- version = gnc_sql_get_table_version (be, TABLE_NAME);
- if (version == 0)
- {
- gnc_sql_create_table (be, TABLE_NAME, TABLE_VERSION, col_table);
- }
-}
-
-/* ================================================================= */
-static gboolean
-save_vendor (GncSqlBackend* be, QofInstance* inst)
+bool
+GncSqlVendorBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
GncVendor* v;
const GncGUID* guid;
@@ -218,27 +214,24 @@ vendor_should_be_saved (GncVendor* vendor)
static void
write_single_vendor (QofInstance* term_p, gpointer data_p)
{
- write_objects_t* s = (write_objects_t*)data_p;
+ auto s = reinterpret_cast<write_objects_t*>(data_p);
g_return_if_fail (term_p != NULL);
g_return_if_fail (GNC_IS_VENDOR (term_p));
g_return_if_fail (data_p != NULL);
- if (s->is_ok && vendor_should_be_saved (GNC_VENDOR (term_p)))
+ if (vendor_should_be_saved (GNC_VENDOR (term_p)))
{
- s->is_ok = save_vendor (s->be, term_p);
+ s->commit (term_p);
}
}
-static gboolean
-write_vendors (GncSqlBackend* be)
+bool
+GncSqlVendorBackend::write (GncSqlBackend* be)
{
- write_objects_t data;
-
g_return_val_if_fail (be != NULL, FALSE);
+ write_objects_t data{be, true, this};
- data.be = be;
- data.is_ok = TRUE;
qof_object_foreach (GNC_ID_VENDOR, be->book, write_single_vendor, &data);
return data.is_ok;
@@ -248,16 +241,8 @@ write_vendors (GncSqlBackend* be)
void
gnc_vendor_sql_initialize (void)
{
- static GncSqlObjectBackend be_data =
- {
- GNC_SQL_BACKEND_VERSION,
- GNC_ID_VENDOR,
- save_vendor, /* commit */
- load_all_vendors, /* initial_load */
- create_vendor_tables, /* create_tables */
- NULL, NULL, NULL,
- write_vendors /* write */
- };
+ static GncSqlVendorBackend be_data {
+ GNC_SQL_BACKEND_VERSION, GNC_ID_VENDOR, TABLE_NAME, col_table};
gnc_sql_register_backend(&be_data);
}
commit 6e84ccac75f7009e2864c56d165cfcd29a39aa2e
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Jun 9 14:23:42 2016 -0700
Move GncSqlColumnTypeHandler functions into GncSqlColumnTableEntry.
Unfortunately a rather massive change. Gets rid of GncSqlColumnTypeHandler
and its hideous run-time registry by making the handler functions members
of GncSqlColumnTableEntry. GncSqlColumnTableEntry becomes an abstract super-
class with a templatized subclass GncSqlColumnTableEntryImpl whose template
parameter is the GncSqlObjectType that's also the GncSqlColumnTableEntryImpl's
m_col_type member. That member is a candidate for future removal as it's not
necessary. An explicit specialization is provided for each GncSqlObjectType and
that's a candidate for future code-shrinkage as there's still a fair amount
of duplication in spite of adding several helper template functions to absorb
most of the meat. The abstract GncSqlColumnTableEntry class is motivated by
the need to have an iterable container which in turn requires runtime
polymorphism. This can probably be replaced with a variadic-template
pseudo-container.
The two major benefits of this change are that it gets rid of one more set
of macro functions and provides vtable dispatch that has only one level
of indirection instead of the cumbersome string-hash-table-lookup to
find the handler followed by invoking the handler's function.
The two header files are removed because they exposed only the initialization
function which in turn only registered the respective GncSqlColumnTypeHandler.
diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 3b6ead6..2d70f7a 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -2544,13 +2544,13 @@ create_index_ddl (GncSqlConnection* conn, const char* index_name,
ddl = g_string_new ("");
g_string_printf (ddl, "CREATE INDEX %s ON %s (", index_name, table_name);
- for (auto const& table_row : col_table)
+ for (auto const table_row : col_table)
{
if (table_row != *col_table.begin())
{
(void)g_string_append (ddl, ", ");
}
- g_string_append_printf (ddl, "%s", table_row.col_name);
+ g_string_append_printf (ddl, "%s", table_row->name());
}
(void)g_string_append (ddl, ")");
diff --git a/src/backend/sql/CMakeLists.txt b/src/backend/sql/CMakeLists.txt
index b50d7fe..6c4ece5 100644
--- a/src/backend/sql/CMakeLists.txt
+++ b/src/backend/sql/CMakeLists.txt
@@ -29,7 +29,6 @@ SET (backend_sql_SOURCES
)
SET (backend_sql_noinst_HEADERS
gnc-account-sql.h
- gnc-address-sql.h
gnc-backend-sql.h
gnc-bill-term-sql.h
gnc-book-sql.h
@@ -42,7 +41,6 @@ SET (backend_sql_noinst_HEADERS
gnc-job-sql.h
gnc-lots-sql.h
gnc-order-sql.h
- gnc-owner-sql.h
gnc-price-sql.h
gnc-recurrence-sql.h
gnc-schedxaction-sql.h
diff --git a/src/backend/sql/Makefile.am b/src/backend/sql/Makefile.am
index 20463e2..6f0dabe 100644
--- a/src/backend/sql/Makefile.am
+++ b/src/backend/sql/Makefile.am
@@ -47,7 +47,6 @@ libgnc_backend_sql_la_SOURCES = \
noinst_HEADERS = \
gnc-account-sql.h \
- gnc-address-sql.h \
gnc-backend-sql.h \
gnc-bill-term-sql.h \
gnc-book-sql.h \
@@ -60,7 +59,6 @@ noinst_HEADERS = \
gnc-job-sql.h \
gnc-lots-sql.h \
gnc-order-sql.h \
- gnc-owner-sql.h \
gnc-price-sql.h \
gnc-recurrence-sql.h \
gnc-schedxaction-sql.h \
diff --git a/src/backend/sql/gnc-account-sql.cpp b/src/backend/sql/gnc-account-sql.cpp
index c1079df..a9f3149 100644
--- a/src/backend/sql/gnc-account-sql.cpp
+++ b/src/backend/sql/gnc-account-sql.cpp
@@ -64,24 +64,31 @@ static void set_parent_guid (gpointer pObject, gpointer pValue);
static const EntryVec col_table
{
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "name", CT_STRING, ACCOUNT_MAX_NAME_LEN, COL_NNUL, "name" },
- { "account_type", CT_STRING, ACCOUNT_MAX_TYPE_LEN, COL_NNUL, NULL, ACCOUNT_TYPE_ },
- { "commodity_guid", CT_COMMODITYREF, 0, 0, "commodity" },
- { "commodity_scu", CT_INT, 0, COL_NNUL, "commodity-scu" },
- { "non_std_scu", CT_BOOLEAN, 0, COL_NNUL, "non-std-scu" },
- {
- "parent_guid", CT_GUID, 0, 0, NULL, NULL,
- (QofAccessFunc)get_parent, set_parent
- },
- { "code", CT_STRING, ACCOUNT_MAX_CODE_LEN, 0, "code" },
- { "description", CT_STRING, ACCOUNT_MAX_DESCRIPTION_LEN, 0, "description" },
- { "hidden", CT_BOOLEAN, 0, 0, "hidden" },
- { "placeholder", CT_BOOLEAN, 0, 0, "placeholder" },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid" ),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "name", ACCOUNT_MAX_NAME_LEN, COL_NNUL, "name"),
+ gnc_sql_make_table_entry<CT_STRING>("account_type", ACCOUNT_MAX_TYPE_LEN,
+ COL_NNUL, ACCOUNT_TYPE_, true),
+ gnc_sql_make_table_entry<CT_COMMODITYREF>(
+ "commodity_guid", 0, 0, "commodity"),
+ gnc_sql_make_table_entry<CT_INT>(
+ "commodity_scu", 0, COL_NNUL, "commodity-scu"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>(
+ "non_std_scu", 0, COL_NNUL, "non-std-scu"),
+ gnc_sql_make_table_entry<CT_GUID>("parent_guid", 0, 0,
+ (QofAccessFunc)get_parent,
+ (QofSetterFunc)set_parent),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "code", ACCOUNT_MAX_CODE_LEN, 0, "code"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "description", ACCOUNT_MAX_DESCRIPTION_LEN, 0, "description"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("hidden", 0, 0, "hidden"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("placeholder", 0, 0, "placeholder"),
};
static EntryVec parent_col_table
({
- { "parent_guid", CT_GUID, 0, 0, NULL, NULL, NULL, set_parent_guid },
+ gnc_sql_make_table_entry<CT_GUID>(
+ "parent_guid", 0, 0, nullptr, (QofSetterFunc)set_parent_guid),
});
typedef struct
@@ -386,36 +393,34 @@ gnc_sql_save_account (GncSqlBackend* be, QofInstance* inst)
}
/* ================================================================= */
-static void
-load_account_guid (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
-{
- const GValue* val;
- GncGUID guid;
- Account* account = NULL;
- g_return_if_fail (be != NULL);
- g_return_if_fail (pObject != NULL);
+template<> void
+GncSqlColumnTableEntryImpl<CT_ACCOUNTREF>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
+{
+ load_from_guid_ref(row, obj_name, pObject,
+ [be](GncGUID* g){
+ return xaccAccountLookup(g, be->book);
+ });
+}
- try
- {
- auto val = row.get_string_at_col (table_row.col_name);
- (void)string_to_guid (val.c_str(), &guid);
- account = xaccAccountLookup (&guid, be->book);
- if (account != nullptr)
- set_parameter (pObject, account, setter, table_row.gobj_param_name);
- else
- PWARN ("Account ref '%s' not found", val.c_str());
- }
- catch (std::invalid_argument) {}
+template<> void
+GncSqlColumnTableEntryImpl<CT_ACCOUNTREF>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
+{
+ add_objectref_guid_to_table(be, vec);
}
-static GncSqlColumnTypeHandler account_guid_handler
-= { load_account_guid,
- gnc_sql_add_objectref_guid_col_info_to_list,
- gnc_sql_add_objectref_guid_to_vec
- };
+template<> void
+GncSqlColumnTableEntryImpl<CT_ACCOUNTREF>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
+{
+ add_objectref_guid_to_query(be, obj_name, pObject, vec);
+}
/* ================================================================= */
void
gnc_sql_init_account_handler (void)
@@ -434,7 +439,5 @@ gnc_sql_init_account_handler (void)
};
gnc_sql_register_backend(&be_data);
-
- gnc_sql_register_col_type_handler (CT_ACCOUNTREF, &account_guid_handler);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-address-sql.cpp b/src/backend/sql/gnc-address-sql.cpp
index 713ea04..c60ff72 100644
--- a/src/backend/sql/gnc-address-sql.cpp
+++ b/src/backend/sql/gnc-address-sql.cpp
@@ -40,7 +40,6 @@ extern "C"
#include "gncAddress.h"
}
#include "gnc-backend-sql.h"
-#include "gnc-address-sql.h"
G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
@@ -52,23 +51,32 @@ G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
static EntryVec col_table
({
- { "name", CT_STRING, ADDRESS_MAX_NAME_LEN, COL_NNUL, "name" },
- { "addr1", CT_STRING, ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, "addr1" },
- { "addr2", CT_STRING, ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, "addr2" },
- { "addr3", CT_STRING, ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, "addr3" },
- { "addr4", CT_STRING, ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, "addr4" },
- { "phone", CT_STRING, ADDRESS_MAX_PHONE_LEN, COL_NNUL, "phone" },
- { "fax", CT_STRING, ADDRESS_MAX_FAX_LEN, COL_NNUL, "fax" },
- { "email", CT_STRING, ADDRESS_MAX_EMAIL_LEN, COL_NNUL, "email" },
+ std::make_shared<GncSqlColumnTableEntryImpl<CT_STRING>>(
+ "name", CT_STRING, ADDRESS_MAX_NAME_LEN, COL_NNUL, "name"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "addr1", ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, "addr1"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "addr2", ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, "addr2"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "addr3", ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, "addr3"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "addr4", ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, "addr4"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "phone", ADDRESS_MAX_PHONE_LEN, COL_NNUL, "phone"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "fax", ADDRESS_MAX_FAX_LEN, COL_NNUL, "fax" ),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "email", ADDRESS_MAX_EMAIL_LEN, COL_NNUL, "email"),
});
typedef void (*AddressSetterFunc) (gpointer, GncAddress*);
typedef GncAddress* (*AddressGetterFunc) (const gpointer);
-static void
-load_address (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_ADDRESS>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
const gchar* s;
@@ -80,19 +88,13 @@ load_address (const GncSqlBackend* be, GncSqlRow& row,
for (auto const& subtable_row : col_table)
{
- auto buf = g_strdup_printf ("%s_%s", table_row.col_name,
- subtable_row.col_name);
+ auto buf = std::string{m_col_name} + "_" + subtable_row->m_col_name;
try
{
- auto val = row.get_string_at_col (buf);
- g_free (buf);
- auto sub_setter = subtable_row.setter;
- auto pname = subtable_row.qof_param_name;
- if (pname != nullptr)
- sub_setter = qof_class_get_parameter_setter (GNC_ID_ADDRESS,
- pname);
+ auto val = row.get_string_at_col (buf.c_str());
+ auto sub_setter = subtable_row->get_setter(GNC_ID_ADDRESS);
set_parameter (addr, val.c_str(), sub_setter,
- subtable_row.gobj_param_name);
+ subtable_row->m_gobj_param_name);
}
catch (std::invalid_argument)
{
@@ -100,65 +102,44 @@ load_address (const GncSqlBackend* be, GncSqlRow& row,
}
}
set_parameter (pObject, addr,
- reinterpret_cast<AddressSetterFunc>(setter),
- table_row.gobj_param_name);
+ reinterpret_cast<AddressSetterFunc>(get_setter(obj_name)),
+ m_gobj_param_name);
}
-static void
-add_address_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_ADDRESS>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
- GncSqlColumnInfo* info;
- gchar* buf;
-
g_return_if_fail (be != NULL);
-
for (auto const& subtable_row : col_table)
{
- buf = g_strdup_printf ("%s_%s", table_row.col_name, subtable_row.col_name);
-
- GncSqlColumnInfo info(buf, BCT_STRING, subtable_row.size, true, false,
- table_row.flags & COL_PKEY,
- table_row.flags & COL_NNUL);
+ auto buf = std::string{m_col_name} + "_" + subtable_row->m_col_name;
+ GncSqlColumnInfo info(buf.c_str(), BCT_STRING, subtable_row->m_size,
+ true, false, m_flags & COL_PKEY, m_flags & COL_NNUL);
vec.emplace_back(std::move(info));
}
}
-static void
-add_value_address_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
+/* char is unusual in that we get a pointer but don't deref it to pass
+ * it to operator<<().
+ */
+template<> void
+GncSqlColumnTableEntryImpl<CT_ADDRESS>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
- auto addr = get_row_value_from_object<GncAddress*>(obj_name, pObject,
- table_row);
-
+ auto addr{get_row_value_from_object<char*>(obj_name, pObject)};
+ if (addr == nullptr) return;
- if (addr == nullptr)
- return;
for (auto const& subtable_row : col_table)
{
- auto s = get_row_value_from_object<char*>(GNC_ID_ADDRESS, addr,
- subtable_row);
+ auto s = subtable_row->get_row_value_from_object<char*>(GNC_ID_ADDRESS,
+ addr);
if (s == nullptr)
continue;
- std::ostringstream buf;
- buf << table_row.col_name << "_" << subtable_row.col_name;
- vec.emplace_back(make_pair(buf.str(), std::string{s}));
+ auto buf = std::string{m_col_name} + "_" + subtable_row->m_col_name;
+ vec.emplace_back(make_pair(buf, std::string{s}));
}
}
-
-static GncSqlColumnTypeHandler address_handler
-= { load_address,
- add_address_col_info_to_list,
- add_value_address_to_vec
- };
-
-/* ================================================================= */
-void
-gnc_address_sql_initialize (void)
-{
- gnc_sql_register_col_type_handler (CT_ADDRESS, &address_handler);
-}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-address-sql.h b/src/backend/sql/gnc-address-sql.h
deleted file mode 100644
index fcc4d47..0000000
--- a/src/backend/sql/gnc-address-sql.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* gnc-address-sql.h -- Address SQL header
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, contact:
- *
- * Free Software Foundation Voice: +1-617-542-5942
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
- * Boston, MA 02110-1301, USA gnu at gnu.org
- */
-
-/** @file gnc-address-sql.h
- * @brief load and save address data to SQL
- * @author Copyright (c) 2007-2008 Phil Longstaff <plongstaff at rogers.com>
- *
- * This file implements the top-level QofBackend API for saving/
- * restoring data to/from an SQL database
- */
-
-#ifndef GNC_ADDRESS_SQL_H
-#define GNC_ADDRESS_SQL_H
-
-void gnc_address_sql_initialize (void);
-
-#endif /* GNC_ADDRESS_SQL_H */
diff --git a/src/backend/sql/gnc-backend-sql.cpp b/src/backend/sql/gnc-backend-sql.cpp
index cdd5d53..d03ca29 100644
--- a/src/backend/sql/gnc-backend-sql.cpp
+++ b/src/backend/sql/gnc-backend-sql.cpp
@@ -72,7 +72,6 @@ extern "C"
#include "gnc-slots-sql.h"
#include "gnc-transaction-sql.h"
-#include "gnc-address-sql.h"
#include "gnc-bill-term-sql.h"
#include "gnc-customer-sql.h"
#include "gnc-employee-sql.h"
@@ -80,14 +79,12 @@ extern "C"
#include "gnc-invoice-sql.h"
#include "gnc-job-sql.h"
#include "gnc-order-sql.h"
-#include "gnc-owner-sql.h"
#include "gnc-tax-table-sql.h"
#include "gnc-vendor-sql.h"
static void gnc_sql_init_object_handlers (void);
static void update_progress (GncSqlBackend* be);
static void finish_progress (GncSqlBackend* be);
-static void register_standard_col_type_handlers (void);
static gboolean reset_version_info (GncSqlBackend* be);
static GncSqlStatement* build_insert_statement (GncSqlBackend* be,
const gchar* table_name,
@@ -154,7 +151,6 @@ gnc_sql_init(GncSqlBackend* be)
if (!initialized)
{
- register_standard_col_type_handlers ();
gnc_sql_init_object_handlers ();
initialized = TRUE;
}
@@ -1066,7 +1062,6 @@ static void
business_core_sql_init (void)
{
/* Initialize our pointers into the backend subsystem */
- gnc_address_sql_initialize ();
gnc_billterm_sql_initialize ();
gnc_customer_sql_initialize ();
gnc_employee_sql_initialize ();
@@ -1074,7 +1069,6 @@ business_core_sql_init (void)
gnc_invoice_sql_initialize ();
gnc_job_sql_initialize ();
gnc_order_sql_initialize ();
- gnc_owner_sql_initialize ();
gnc_taxtable_sql_initialize ();
gnc_vendor_sql_initialize ();
@@ -1157,224 +1151,261 @@ set_autoinc_id (void* object, void* item)
}
QofAccessFunc
-gnc_sql_get_getter (QofIdTypeConst obj_name,
- const GncSqlColumnTableEntry& table_row)
+GncSqlColumnTableEntry::get_getter (QofIdTypeConst obj_name) const noexcept
{
QofAccessFunc getter;
g_return_val_if_fail (obj_name != NULL, NULL);
- if (table_row.flags & COL_AUTOINC)
+ if (m_flags & COL_AUTOINC)
{
getter = get_autoinc_id;
}
- else if (table_row.qof_param_name != NULL)
+ else if (m_qof_param_name != NULL)
{
- getter = qof_class_get_parameter_getter (obj_name,
- table_row.qof_param_name);
+ getter = qof_class_get_parameter_getter (obj_name, m_qof_param_name);
}
else
{
- getter = table_row.getter;
+ getter = m_getter;
}
return getter;
}
+QofSetterFunc
+GncSqlColumnTableEntry::get_setter(QofIdTypeConst obj_name) const noexcept
+{
+ QofSetterFunc setter = nullptr;
+ if (m_flags & COL_AUTOINC)
+ {
+ setter = set_autoinc_id;
+ }
+ else if (m_qof_param_name != nullptr)
+ {
+ g_assert (obj_name != NULL);
+ setter = qof_class_get_parameter_setter (obj_name, m_qof_param_name);
+ }
+ else
+ {
+ setter = m_setter;
+ }
+ return setter;
+}
+
+void
+GncSqlColumnTableEntry::add_objectref_guid_to_query (const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
+{
+ auto inst = get_row_value_from_object<QofInstance*>(obj_name, pObject);
+ if (inst == nullptr) return;
+ auto guid = qof_instance_get_guid (inst);
+ if (guid != nullptr)
+ vec.emplace_back (std::make_pair (std::string{m_col_name},
+ std::string{guid_to_string(guid)}));
+}
+
+void
+GncSqlColumnTableEntry::add_objectref_guid_to_table (const GncSqlBackend* be,
+ ColVec& vec) const noexcept
+{
+ g_return_if_fail (be != NULL);
+
+ GncSqlColumnInfo info{*this, BCT_STRING, GUID_ENCODING_LENGTH, FALSE};
+ vec.emplace_back(std::move(info));
+}
+
/* ----------------------------------------------------------------- */
-static void
-load_string (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_STRING>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
g_return_if_fail (pObject != NULL);
- g_return_if_fail (table_row.gobj_param_name != NULL || setter != NULL);
+ g_return_if_fail (m_gobj_param_name != NULL || get_setter(obj_name) != NULL);
try
{
- auto s = row.get_string_at_col (table_row.col_name);
- set_parameter(pObject, s.c_str(), setter, table_row.gobj_param_name);
+ auto s = row.get_string_at_col (m_col_name);
+ set_parameter(pObject, s.c_str(), get_setter(obj_name), m_gobj_param_name);
}
catch (std::invalid_argument) {}
}
-static void
-add_string_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_STRING>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
- GncSqlColumnInfo info{table_row, BCT_STRING, table_row.size, TRUE};
+ GncSqlColumnInfo info{*this, BCT_STRING, m_size, TRUE};
vec.emplace_back(std::move(info));
}
/* char is unusual in that we get a pointer but don't deref it to pass
* it to operator<<().
*/
-template <> void
-add_value_to_vec<char*>(const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_STRING>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
- auto s = get_row_value_from_object<char*>(obj_name, pObject, table_row);
+ auto s = get_row_value_from_object<char*>(obj_name, pObject);
if (s != nullptr)
{
std::ostringstream stream;
stream << s;
- vec.emplace_back (std::make_pair (std::string{table_row.col_name},
- stream.str()));
+ vec.emplace_back (std::make_pair (std::string{m_col_name}, stream.str()));
return;
}
}
-static GncSqlColumnTypeHandler string_handler
-=
-{
- load_string,
- add_string_col_info_to_list,
- add_value_to_vec<char*>
-};
/* ----------------------------------------------------------------- */
typedef gint (*IntAccessFunc) (const gpointer);
typedef void (*IntSetterFunc) (const gpointer, gint);
-static void
-load_int (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_INT>::load (const GncSqlBackend* be, GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
g_return_if_fail (pObject != NULL);
- g_return_if_fail (table_row.gobj_param_name != NULL || setter != NULL);
+ g_return_if_fail (m_gobj_param_name != NULL || get_setter(obj_name) != NULL);
- auto val = row.get_int_at_col(table_row.col_name);
+ auto val = row.get_int_at_col(m_col_name);
set_parameter(pObject, val,
- reinterpret_cast<IntSetterFunc>(setter),
- table_row.gobj_param_name);
+ reinterpret_cast<IntSetterFunc>(get_setter(obj_name)), m_gobj_param_name);
}
-static void
-add_int_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_INT>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
- GncSqlColumnInfo info{table_row, BCT_INT, 0, FALSE};
+ GncSqlColumnInfo info{*this, BCT_INT, 0, FALSE};
vec.emplace_back(std::move(info));
}
-static GncSqlColumnTypeHandler int_handler
-=
+template<> void
+GncSqlColumnTableEntryImpl<CT_INT>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
- load_int,
- add_int_col_info_to_list,
- add_value_to_vec<int>
-};
+ add_value_to_vec<int>(be, obj_name, pObject, vec);
+}
/* ----------------------------------------------------------------- */
typedef gboolean (*BooleanAccessFunc) (const gpointer);
typedef void (*BooleanSetterFunc) (const gpointer, gboolean);
-static void
-load_boolean (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_BOOLEAN>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject)
+ const noexcept
{
g_return_if_fail (pObject != NULL);
- g_return_if_fail (table_row.gobj_param_name != NULL || setter != NULL);
+ g_return_if_fail (m_gobj_param_name != NULL || get_setter(obj_name) != NULL);
- auto val = row.get_int_at_col (table_row.col_name);
+ auto val = row.get_int_at_col (m_col_name);
set_parameter(pObject, val,
- reinterpret_cast<BooleanSetterFunc>(setter),
- table_row.gobj_param_name);
+ reinterpret_cast<BooleanSetterFunc>(get_setter(obj_name)),
+ m_gobj_param_name);
}
-static void
-add_boolean_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_BOOLEAN>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
- GncSqlColumnInfo info{table_row, BCT_INT, 0, FALSE};
+ GncSqlColumnInfo info{*this, BCT_INT, 0, FALSE};
vec.emplace_back(std::move(info));
}
-static GncSqlColumnTypeHandler boolean_handler
-=
+template<> void
+GncSqlColumnTableEntryImpl<CT_BOOLEAN>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
- load_boolean,
- add_boolean_col_info_to_list,
- add_value_to_vec<int>
-};
+ add_value_to_vec<int>(be, obj_name, pObject, vec);
+}
/* ----------------------------------------------------------------- */
typedef gint64 (*Int64AccessFunc) (const gpointer);
typedef void (*Int64SetterFunc) (const gpointer, gint64);
-static void
-load_int64 (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_INT64>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject)
+ const noexcept
{
- g_return_if_fail (table_row.gobj_param_name != nullptr ||
- setter != nullptr);
+ g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
- auto val = row.get_int_at_col (table_row.col_name);
+ auto val = row.get_int_at_col (m_col_name);
set_parameter(pObject, val,
- reinterpret_cast<Int64SetterFunc>(setter),
- table_row.gobj_param_name);
+ reinterpret_cast<Int64SetterFunc>(get_setter(obj_name)),
+ m_gobj_param_name);
}
-static void
-add_int64_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_INT64>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
- GncSqlColumnInfo info{table_row, BCT_INT64, 0, FALSE};
+ GncSqlColumnInfo info{*this, BCT_INT64, 0, FALSE};
vec.emplace_back(std::move(info));
}
-static GncSqlColumnTypeHandler int64_handler
-=
+template<> void
+GncSqlColumnTableEntryImpl<CT_INT64>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
- load_int64,
- add_int64_col_info_to_list,
- add_value_to_vec<int64_t>
-};
+ add_value_to_vec<int64_t>(be, obj_name, pObject, vec);
+}
/* ----------------------------------------------------------------- */
-static void
-load_double (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_DOUBLE>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject)
+ const noexcept
{
g_return_if_fail (pObject != NULL);
- g_return_if_fail (table_row.gobj_param_name != nullptr ||
- setter != nullptr);
+ g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
double val;
try
{
- val = static_cast<double>(row.get_int_at_col(table_row.col_name));
+ val = static_cast<double>(row.get_int_at_col(m_col_name));
}
catch (std::invalid_argument)
{
try
{
- val = static_cast<double>(row.get_float_at_col(table_row.col_name));
+ val = static_cast<double>(row.get_float_at_col(m_col_name));
}
catch (std::invalid_argument)
{
try
{
- val = row.get_double_at_col(table_row.col_name);
+ val = row.get_double_at_col(m_col_name);
}
catch (std::invalid_argument)
{
@@ -1382,121 +1413,83 @@ load_double (const GncSqlBackend* be, GncSqlRow& row,
}
}
}
- set_parameter(pObject, val, setter, table_row.gobj_param_name);
+ set_parameter(pObject, val, get_setter(obj_name), m_gobj_param_name);
}
-static void
-add_double_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_DOUBLE>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
- GncSqlColumnInfo info{table_row, BCT_DOUBLE, 0, FALSE};
+ GncSqlColumnInfo info{*this, BCT_DOUBLE, 0, FALSE};
vec.emplace_back(std::move(info));
}
-static GncSqlColumnTypeHandler double_handler
-=
+template<> void
+GncSqlColumnTableEntryImpl<CT_DOUBLE>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
- load_double,
- add_double_col_info_to_list,
- add_value_to_vec<double*>
-};
+ add_value_to_vec<double*>(be, obj_name, pObject, vec);
+}
+
/* ----------------------------------------------------------------- */
-static void
-load_guid (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_GUID>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject)
+ const noexcept
{
GncGUID guid;
const GncGUID* pGuid;
g_return_if_fail (pObject != NULL);
- g_return_if_fail (table_row.gobj_param_name != nullptr ||
- setter != nullptr);
+ g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
std::string str;
try
{
- str = row.get_string_at_col(table_row.col_name);
+ str = row.get_string_at_col(m_col_name);
}
catch (std::invalid_argument)
{
return;
}
(void)string_to_guid (str.c_str(), &guid);
- set_parameter(pObject, &guid, setter, table_row.gobj_param_name);
+ set_parameter(pObject, &guid, get_setter(obj_name), m_gobj_param_name);
}
-static void
-add_guid_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_GUID>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
- GncSqlColumnInfo info{table_row, BCT_STRING, GUID_ENCODING_LENGTH, FALSE};
+ GncSqlColumnInfo info{*this, BCT_STRING, GUID_ENCODING_LENGTH, FALSE};
vec.emplace_back(std::move(info));
}
-template <> void
-add_value_to_vec<GncGUID>(const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_GUID>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
- auto s = get_row_value_from_object<GncGUID*>(obj_name, pObject, table_row);
+ auto s = get_row_value_from_object<GncGUID*>(obj_name, pObject);
if (s != nullptr)
{
- std::ostringstream stream;
- stream << guid_to_string(s);
- vec.emplace_back (std::make_pair (std::string{table_row.col_name},
- stream.str()));
- return;
- }
-}
-
-static GncSqlColumnTypeHandler guid_handler
-=
-{
- load_guid,
- add_guid_col_info_to_list,
- add_value_to_vec<GncGUID>
-};
-/* ----------------------------------------------------------------- */
-void
-gnc_sql_add_objectref_guid_to_vec (const GncSqlBackend* be,
- QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
-{
- auto inst = get_row_value_from_object<QofInstance*>(obj_name, pObject,
- table_row);
- const GncGUID* guid = nullptr;
- if (inst != nullptr)
- guid = qof_instance_get_guid (inst);
- if (guid != nullptr)
- {
- vec.emplace_back (std::make_pair (std::string{table_row.col_name},
- std::string{guid_to_string(guid)}));
+ vec.emplace_back (std::make_pair (std::string{m_col_name},
+ std::string{guid_to_string(s)}));
return;
}
}
-
-void
-gnc_sql_add_objectref_guid_col_info_to_list( const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& info_vec)
-{
- add_guid_col_info_to_list(be, table_row, info_vec);
-}
-
/* ----------------------------------------------------------------- */
typedef Timespec (*TimespecAccessFunc) (const gpointer);
typedef void (*TimespecSetterFunc) (const gpointer, Timespec*);
@@ -1528,10 +1521,11 @@ gnc_sql_convert_timespec_to_string (const GncSqlBackend* be, Timespec ts)
}
#pragma GCC diagnostic warning "-Wformat-nonliteral"
-static void
-load_timespec (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_TIMESPEC>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
Timespec ts = {0, 0};
@@ -1539,19 +1533,18 @@ load_timespec (const GncSqlBackend* be, GncSqlRow& row,
g_return_if_fail (pObject != NULL);
- g_return_if_fail (table_row.gobj_param_name != nullptr ||
- setter != nullptr);
+ g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
try
{
- auto val = row.get_time64_at_col(table_row.col_name);
+ auto val = row.get_time64_at_col(m_col_name);
timespecFromTime64 (&ts, val);
}
catch (std::invalid_argument)
{
try
{
- auto val = row.get_string_at_col(table_row.col_name);
+ auto val = row.get_string_at_col(m_col_name);
auto s = val.c_str();
auto buf = g_strdup_printf ("%c%c%c%c-%c%c-%c%c %c%c:%c%c:%c%c",
s[0], s[1], s[2], s[3], s[4], s[5],
@@ -1566,26 +1559,25 @@ load_timespec (const GncSqlBackend* be, GncSqlRow& row,
}
}
set_parameter(pObject, &ts,
- reinterpret_cast<TimespecSetterFunc>(setter),
- table_row.gobj_param_name);
-}
+ reinterpret_cast<TimespecSetterFunc>(get_setter(obj_name)),
+ m_gobj_param_name);
+ }
-static void
-add_timespec_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_TIMESPEC>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
- g_return_if_fail (be != NULL);
+ g_return_if_fail (be != nullptr);
- GncSqlColumnInfo info{table_row, BCT_DATETIME, TIMESPEC_COL_SIZE, FALSE};
+ GncSqlColumnInfo info{*this, BCT_DATETIME, TIMESPEC_COL_SIZE, FALSE};
vec.emplace_back(std::move(info));
}
-static void
-add_timespec_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_TIMESPEC>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
TimespecAccessFunc ts_getter;
Timespec ts;
@@ -1597,15 +1589,15 @@ add_timespec_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
g_return_if_fail (obj_name != NULL);
g_return_if_fail (pObject != NULL);
- if (table_row.gobj_param_name != NULL)
+ if (m_gobj_param_name != NULL)
{
Timespec* pts;
- g_object_get (pObject, table_row.gobj_param_name, &pts, NULL);
+ g_object_get (pObject, m_gobj_param_name, &pts, NULL);
ts = *pts;
}
else
{
- ts_getter = (TimespecAccessFunc)gnc_sql_get_getter (obj_name, table_row);
+ ts_getter = (TimespecAccessFunc)get_getter (obj_name);
g_return_if_fail (ts_getter != NULL);
ts = (*ts_getter) (pObject);
}
@@ -1613,31 +1605,24 @@ add_timespec_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
if (ts.tv_sec != 0 || ts.tv_nsec != 0)
{
char* datebuf = gnc_sql_convert_timespec_to_string (be, ts);
- vec.emplace_back (std::make_pair (std::string{table_row.col_name},
+ vec.emplace_back (std::make_pair (std::string{m_col_name},
std::string{datebuf}));
return;
}
}
-static GncSqlColumnTypeHandler timespec_handler
-=
-{
- load_timespec,
- add_timespec_col_info_to_list,
- add_timespec_to_vec
-};
/* ----------------------------------------------------------------- */
#define DATE_COL_SIZE 8
-static void
-load_date (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_GDATE>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
g_return_if_fail (pObject != NULL);
- g_return_if_fail (table_row.gobj_param_name != nullptr ||
- setter != nullptr);
- if (row.is_col_null(table_row.col_name))
+ g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
+ if (row.is_col_null(m_col_name))
return;
GDate date;
g_date_clear (&date, 1);
@@ -1646,7 +1631,7 @@ load_date (const GncSqlBackend* be, GncSqlRow& row,
/* timespec_to_gdate applies the tz, and gdates are saved
* as ymd, so we don't want that.
*/
- auto time = row.get_time64_at_col(table_row.col_name);
+ auto time = row.get_time64_at_col(m_col_name);
auto tm = gnc_gmtime(&time);
g_date_set_dmy(&date, tm->tm_mday,
static_cast<GDateMonth>(tm->tm_mon + 1),
@@ -1657,7 +1642,7 @@ load_date (const GncSqlBackend* be, GncSqlRow& row,
{
try
{
- std::string str = row.get_string_at_col(table_row.col_name);
+ std::string str = row.get_string_at_col(m_col_name);
if (str.empty()) return;
auto year = static_cast<GDateYear>(stoi (str.substr (0,4)));
auto month = static_cast<GDateMonth>(stoi (str.substr (4,2)));
@@ -1672,74 +1657,65 @@ load_date (const GncSqlBackend* be, GncSqlRow& row,
return;
}
}
- set_parameter(pObject, &date, setter, table_row.gobj_param_name);
+ set_parameter(pObject, &date, get_setter(obj_name), m_gobj_param_name);
}
-static void
-add_date_col_info_to_list (const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_GDATE>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
- GncSqlColumnInfo info{table_row, BCT_DATE, DATE_COL_SIZE, FALSE};
+ GncSqlColumnInfo info{*this, BCT_DATE, DATE_COL_SIZE, FALSE};
vec.emplace_back(std::move(info));
}
-static void
-add_date_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_GDATE>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
- GDate *date = get_row_value_from_object<GDate*>(obj_name, pObject,
- table_row);
+ GDate *date = get_row_value_from_object<GDate*>(obj_name, pObject);
+
if (date && g_date_valid (date))
{
std::ostringstream buf;
buf << std::setfill ('0') << std::setw (4) << g_date_get_year (date) <<
std::setw (2) << g_date_get_month (date) <<
std::setw (2) << static_cast<int>(g_date_get_day (date));
- vec.emplace_back (std::make_pair (std::string{table_row.col_name},
- buf.str()));
+ vec.emplace_back (std::make_pair (std::string{m_col_name}, buf.str()));
return;
}
}
-static GncSqlColumnTypeHandler date_handler
-=
-{
- load_date,
- add_date_col_info_to_list,
- add_date_to_vec
-};
/* ----------------------------------------------------------------- */
typedef gnc_numeric (*NumericGetterFunc) (const gpointer);
typedef void (*NumericSetterFunc) (gpointer, gnc_numeric*);
static const EntryVec numeric_col_table =
{
- { "num", CT_INT64, 0, COL_NNUL, "guid" },
- { "denom", CT_INT64, 0, COL_NNUL, "guid" },
+ gnc_sql_make_table_entry<CT_INT64>("num", 0, COL_NNUL, "guid"),
+ gnc_sql_make_table_entry<CT_INT64>("denom", 0, COL_NNUL, "guid")
};
-static void
-load_numeric (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_NUMERIC>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
g_return_if_fail (pObject != NULL);
- g_return_if_fail (table_row.gobj_param_name != nullptr ||
- setter != nullptr);
+ g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
gnc_numeric n;
try
{
- auto buf = g_strdup_printf ("%s_num", table_row.col_name);
+ auto buf = g_strdup_printf ("%s_num", m_col_name);
auto num = row.get_int_at_col (buf);
g_free (buf);
- buf = g_strdup_printf ("%s_denom", table_row.col_name);
+ buf = g_strdup_printf ("%s_denom", m_col_name);
auto denom = row.get_int_at_col (buf);
n = gnc_numeric_create (num, denom);
}
@@ -1748,33 +1724,31 @@ load_numeric (const GncSqlBackend* be, GncSqlRow& row,
return;
}
set_parameter(pObject, &n,
- reinterpret_cast<NumericSetterFunc>(setter),
- table_row.gobj_param_name);
+ reinterpret_cast<NumericSetterFunc>(get_setter(obj_name)),
+ m_gobj_param_name);
}
-static void
-add_numeric_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_NUMERIC>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
for (auto const& subtable_row : numeric_col_table)
{
- gchar* buf = g_strdup_printf("%s_%s", table_row.col_name,
- subtable_row.col_name);
+ gchar* buf = g_strdup_printf("%s_%s", m_col_name,
+ subtable_row->m_col_name);
GncSqlColumnInfo info(buf, BCT_INT64, 0, false, false,
- table_row.flags & COL_PKEY,
- table_row.flags & COL_NNUL);
+ m_flags & COL_PKEY, m_flags & COL_NNUL);
vec.emplace_back(std::move(info));
}
}
-static void
-add_numeric_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_NUMERIC>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
/* We can't use get_row_value_from_object for the same reason as Timespec. */
NumericGetterFunc getter;
@@ -1784,15 +1758,15 @@ add_numeric_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
g_return_if_fail (obj_name != NULL);
g_return_if_fail (pObject != NULL);
- if (table_row.gobj_param_name != nullptr)
+ if (m_gobj_param_name != nullptr)
{
gnc_numeric* s;
- g_object_get (pObject, table_row.gobj_param_name, &s, NULL);
+ g_object_get (pObject, m_gobj_param_name, &s, NULL);
n = *s;
}
else
{
- getter = (NumericGetterFunc)gnc_sql_get_getter (obj_name, table_row);
+ getter = reinterpret_cast<NumericGetterFunc>(get_getter (obj_name));
if (getter != NULL)
{
n = (*getter) (pObject);
@@ -1804,8 +1778,8 @@ add_numeric_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
}
std::ostringstream buf;
- std::string num_col{table_row.col_name};
- std::string denom_col{table_row.col_name};
+ std::string num_col{m_col_name};
+ std::string denom_col{m_col_name};
num_col += "_num";
denom_col += "_denom";
buf << gnc_numeric_num (n);
@@ -1815,64 +1789,8 @@ add_numeric_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
vec.emplace_back (denom_col, buf.str ());
}
-static GncSqlColumnTypeHandler numeric_handler
-= { load_numeric,
- add_numeric_col_info_to_list,
- add_numeric_to_vec
-};
/* ================================================================= */
-static GHashTable* g_columnTypeHash = NULL;
-
-void
-gnc_sql_register_col_type_handler (const GncSqlObjectType colType,
- const GncSqlColumnTypeHandler* handler)
-{
- g_return_if_fail (handler != NULL);
-
- if (g_columnTypeHash == NULL)
- {
- g_columnTypeHash = g_hash_table_new (g_direct_hash, g_direct_equal);
- g_assert (g_columnTypeHash != NULL);
- }
-
- DEBUG ("Col type %d registered\n", colType);
- g_hash_table_insert (g_columnTypeHash, GINT_TO_POINTER(colType), (gpointer)handler);
-}
-
-static GncSqlColumnTypeHandler*
-get_handler (const GncSqlColumnTableEntry& table_row)
-{
- GncSqlColumnTypeHandler* pHandler;
-
- if (g_columnTypeHash != NULL)
- {
- pHandler = static_cast<decltype(pHandler)>(
- g_hash_table_lookup (g_columnTypeHash, GINT_TO_POINTER(table_row.col_type)));
- g_assert (pHandler != NULL);
- }
- else
- {
- pHandler = NULL;
- }
-
- return pHandler;
-}
-
-static void
-register_standard_col_type_handlers (void)
-{
- gnc_sql_register_col_type_handler (CT_STRING, &string_handler);
- gnc_sql_register_col_type_handler (CT_BOOLEAN, &boolean_handler);
- gnc_sql_register_col_type_handler (CT_INT, &int_handler);
- gnc_sql_register_col_type_handler (CT_INT64, &int64_handler);
- gnc_sql_register_col_type_handler (CT_DOUBLE, &double_handler);
- gnc_sql_register_col_type_handler (CT_GUID, &guid_handler);
- gnc_sql_register_col_type_handler (CT_TIMESPEC, ×pec_handler);
- gnc_sql_register_col_type_handler (CT_GDATE, &date_handler);
- gnc_sql_register_col_type_handler (CT_NUMERIC, &numeric_handler);
-}
-
void
_retrieve_guid_ (gpointer pObject, gpointer pValue)
{
@@ -1889,8 +1807,8 @@ _retrieve_guid_ (gpointer pObject, gpointer pValue)
// Table to retrieve just the guid
static EntryVec guid_table
{
- { "guid", CT_GUID, 0, 0, NULL, NULL, NULL, _retrieve_guid_ },
- };
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, 0, nullptr, _retrieve_guid_)
+};
const GncGUID*
gnc_sql_load_guid (const GncSqlBackend* be, GncSqlRow& row)
@@ -1907,8 +1825,8 @@ gnc_sql_load_guid (const GncSqlBackend* be, GncSqlRow& row)
// Table to retrieve just the guid
static EntryVec tx_guid_table
{
- { "tx_guid", CT_GUID, 0, 0, NULL, NULL, NULL, _retrieve_guid_ },
- };
+ gnc_sql_make_table_entry<CT_GUID>("tx_guid", 0, 0, nullptr, _retrieve_guid_)
+ };
const GncGUID*
@@ -1929,30 +1847,13 @@ gnc_sql_load_object (const GncSqlBackend* be, GncSqlRow& row,
const EntryVec& table)
{
QofSetterFunc setter;
- GncSqlColumnTypeHandler* pHandler;
g_return_if_fail (be != NULL);
g_return_if_fail (pObject != NULL);
for (auto const& table_row : table)
{
- if (table_row.flags & COL_AUTOINC)
- {
- setter = set_autoinc_id;
- }
- else if (table_row.qof_param_name != nullptr)
- {
- g_assert (obj_name != NULL);
- setter = qof_class_get_parameter_setter (obj_name,
- table_row.qof_param_name);
- }
- else
- {
- setter = table_row.setter;
- }
- pHandler = get_handler (table_row);
- g_assert (pHandler != NULL);
- pHandler->load_fn (be, row, setter, pObject, table_row);
+ table_row->load (be, row, obj_name, pObject);
}
}
@@ -1975,18 +1876,13 @@ gnc_sql_create_select_statement (GncSqlBackend* be, const gchar* table_name)
static GncSqlStatement*
create_single_col_select_statement (GncSqlBackend* be,
const gchar* table_name,
- const GncSqlColumnTableEntry& table_row)
+ const GncSqlColumnTableEntryPtr table_row)
{
- gchar* sql;
- GncSqlStatement* stmt;
-
g_return_val_if_fail (be != NULL, NULL);
g_return_val_if_fail (table_name != NULL, NULL);
- sql = g_strdup_printf ("SELECT %s FROM %s", table_row.col_name, table_name);
- stmt = gnc_sql_create_statement_from_sql (be, sql);
- g_free (sql);
- return stmt;
+ auto sql = std::string{"SELECT "} + table_row->name() + " FROM " + table_name;
+ return gnc_sql_create_statement_from_sql (be, sql.c_str());
}
/* ================================================================= */
@@ -2101,6 +1997,22 @@ gnc_sql_append_guid_list_to_sql (GString* sql, GList* list, guint maxCount)
return count;
}
/* ================================================================= */
+static PairVec
+get_object_values (GncSqlBackend* be, QofIdTypeConst obj_name,
+ gpointer pObject, const EntryVec& table)
+{
+ PairVec vec;
+
+ for (auto const& table_row : table)
+ {
+ if (!(table_row->is_autoincr()))
+ {
+ table_row->add_to_query (be, obj_name, pObject, vec);
+ }
+ }
+ return vec;
+}
+
gboolean
gnc_sql_object_is_it_in_db (GncSqlBackend* be, const gchar* table_name,
@@ -2108,9 +2020,6 @@ gnc_sql_object_is_it_in_db (GncSqlBackend* be, const gchar* table_name,
const EntryVec& table)
{
guint count;
- GncSqlColumnTypeHandler* pHandler;
- PairVec values;
-
g_return_val_if_fail (be != NULL, FALSE);
g_return_val_if_fail (table_name != NULL, FALSE);
g_return_val_if_fail (obj_name != NULL, FALSE);
@@ -2121,9 +2030,7 @@ gnc_sql_object_is_it_in_db (GncSqlBackend* be, const gchar* table_name,
g_assert (stmt != NULL);
/* WHERE */
- pHandler = get_handler (table[0]);
- g_assert (pHandler != NULL);
- pHandler->add_value_to_vec_fn (be, obj_name, pObject, table[0], values);
+ PairVec values{get_object_values(be, obj_name, pObject, table)};
stmt->add_where_cond(obj_name, values);
auto result = gnc_sql_execute_select_statement (be, stmt);
delete stmt;
@@ -2188,26 +2095,6 @@ gnc_sql_do_db_operation (GncSqlBackend* be,
return ok;
}
-static PairVec
-get_object_values (GncSqlBackend* be, QofIdTypeConst obj_name,
- gpointer pObject, const EntryVec& table)
-{
- PairVec vec;
- GncSqlColumnTypeHandler* pHandler;
-
- for (auto const& table_row : table)
- {
- if (!(table_row.flags & COL_AUTOINC))
- {
- pHandler = get_handler (table_row);
- g_assert (pHandler != NULL);
- pHandler->add_value_to_vec_fn (be, obj_name, pObject,
- table_row, vec);
- }
- }
- return vec;
-}
-
static GncSqlStatement*
build_insert_statement (GncSqlBackend* be,
const gchar* table_name,
@@ -2291,7 +2178,6 @@ build_delete_statement (GncSqlBackend* be,
const EntryVec& table)
{
GncSqlStatement* stmt;
- GncSqlColumnTypeHandler* pHandler;
std::ostringstream sql;
g_return_val_if_fail (be != NULL, NULL);
@@ -2304,10 +2190,8 @@ build_delete_statement (GncSqlBackend* be,
sql.str().c_str());
/* WHERE */
- pHandler = get_handler (table[0]);
- g_assert (pHandler != NULL);
PairVec values;
- pHandler->add_value_to_vec_fn (be, obj_name, pObject, table[0], values);
+ table[0]->add_to_query (be, obj_name, pObject, values);
PairVec col_values{values[0]};
stmt->add_where_cond (obj_name, col_values);
@@ -2371,9 +2255,7 @@ do_create_table (const GncSqlBackend* be, const gchar* table_name,
for (auto const& table_row : col_table)
{
- GncSqlColumnTypeHandler* pHandler = get_handler (table_row);
- g_assert (pHandler != NULL);
- pHandler->add_col_info_to_list_fn (be, table_row, info_vec);
+ table_row->add_to_table (be, info_vec);
}
ok = gnc_sql_connection_create_table (be->conn, table_name, info_vec);
return ok;
@@ -2483,11 +2365,7 @@ gboolean gnc_sql_add_columns_to_table (GncSqlBackend* be, const gchar* table_nam
for (auto const& table_row : new_col_table)
{
- GncSqlColumnTypeHandler* pHandler;
-
- pHandler = get_handler (table_row);
- g_assert (pHandler != NULL);
- pHandler->add_col_info_to_list_fn (be, table_row, info_vec);
+ table_row->add_to_table (be, info_vec);
}
ok = gnc_sql_connection_add_columns_to_table(be->conn, table_name, info_vec);
return ok;
@@ -2501,9 +2379,10 @@ gboolean gnc_sql_add_columns_to_table (GncSqlBackend* be, const gchar* table_nam
static EntryVec version_table
{
- { TABLE_COL_NAME, CT_STRING, MAX_TABLE_NAME_LEN, COL_PKEY | COL_NNUL },
- { VERSION_COL_NAME, CT_INT, 0, COL_NNUL },
- };
+ gnc_sql_make_table_entry<CT_STRING>(
+ TABLE_COL_NAME, MAX_TABLE_NAME_LEN, COL_PKEY | COL_NNUL),
+ gnc_sql_make_table_entry<CT_INT>(VERSION_COL_NAME, 0, COL_NNUL)
+};
/**
* Sees if the version table exists, and if it does, loads the info into
@@ -2649,17 +2528,17 @@ gnc_sql_set_table_version (GncSqlBackend* be, const gchar* table_name,
*/
#ifdef __LP64__
template <> int
-get_row_value_from_object<int>(QofIdTypeConst obj_name, const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- std::false_type)
+GncSqlColumnTableEntry::get_row_value_from_object<int>(QofIdTypeConst obj_name,
+ const gpointer pObject,
+ std::false_type) const
{
g_return_val_if_fail(obj_name != nullptr && pObject != nullptr, 0);
int result = 0;
- if (table_row.gobj_param_name != nullptr)
- g_object_get(pObject, table_row.gobj_param_name, &result, NULL );
+ if (m_gobj_param_name != nullptr)
+ g_object_get(pObject, m_gobj_param_name, &result, NULL );
else
{
- QofAccessFunc getter = gnc_sql_get_getter(obj_name, table_row);
+ QofAccessFunc getter = get_getter(obj_name);
if (getter != nullptr)
{
auto value = ((getter)(pObject, nullptr));
diff --git a/src/backend/sql/gnc-backend-sql.h b/src/backend/sql/gnc-backend-sql.h
index 817ee00..5cb0279 100644
--- a/src/backend/sql/gnc-backend-sql.h
+++ b/src/backend/sql/gnc-backend-sql.h
@@ -49,10 +49,12 @@ extern "C"
#include <sstream>
#include <string>
#include <vector>
+#include <memory>
struct GncSqlColumnInfo;
-struct GncSqlColumnTableEntry;
-using EntryVec = std::vector<GncSqlColumnTableEntry>;
+class GncSqlColumnTableEntry;
+using GncSqlColumnTableEntryPtr = std::shared_ptr<GncSqlColumnTableEntry>;
+using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
using ColVec = std::vector<GncSqlColumnInfo>;
using StrVec = std::vector<std::string>;
using PairVec = std::vector<std::pair<std::string, std::string>>;
@@ -389,47 +391,188 @@ enum ColumnFlags : int
* The database description for an object consists of an array of
* GncSqlColumnTableEntry objects, with a final member having col_name == NULL.
*/
-struct GncSqlColumnTableEntry
+
+class GncSqlColumnTableEntry
{
- GncSqlColumnTableEntry (const char* name, const GncSqlObjectType type,
- unsigned int s,
- ColumnFlags f, const char* gobj_name = nullptr,
- const char* qof_name = nullptr,
- QofAccessFunc get = nullptr,
- QofSetterFunc set = nullptr) :
- col_name{name}, col_type{type}, size{s}, flags{f},
- gobj_param_name{gobj_name}, qof_param_name{qof_name}, getter{get},
- setter{set} {}
+public:
GncSqlColumnTableEntry (const char* name, const GncSqlObjectType type,
unsigned int s,
int f, const char* gobj_name = nullptr,
const char* qof_name = nullptr,
QofAccessFunc get = nullptr,
QofSetterFunc set = nullptr) :
- col_name{name}, col_type{type}, size{s},
- flags{static_cast<ColumnFlags>(f)},
- gobj_param_name{gobj_name}, qof_param_name{qof_name}, getter{get},
- setter{set} {}
- const char* col_name; /**< Column name */
- const GncSqlObjectType col_type; /**< Column type */
- unsigned int size; /**< Column size in bytes, for string columns */
- ColumnFlags flags; /**< Column flags */
- const char* gobj_param_name; /**< If non-null, g_object param name */
- const char* qof_param_name; /**< If non-null, qof parameter name */
- QofAccessFunc getter; /**< General access function */
- QofSetterFunc setter; /**< General setter function */
+ m_col_name{name}, m_col_type{type}, m_size{s},
+ m_flags{static_cast<ColumnFlags>(f)},
+ m_gobj_param_name{gobj_name}, m_qof_param_name{qof_name}, m_getter{get},
+ m_setter{set} {}
+
+ /**
+ * Load a value into an object from the database row.
+ */
+ virtual void load(const GncSqlBackend* be, GncSqlRow& row,
+ QofIdTypeConst obj_name, gpointer pObject) const noexcept = 0;
+ /**
+ * Add a GncSqlColumnInfo structure for the column type to a
+ * ColVec.
+ */
+ virtual void add_to_table(const GncSqlBackend* be, ColVec& vec) const noexcept = 0;
+ /**
+ * Add a pair of the table column heading and object's value's string
+ * representation to a PairVec; used for constructing WHERE clauses and
+ * UPDATE statements.
+ */
+ virtual void add_to_query(const GncSqlBackend* be, QofIdTypeConst obj_name,
+ gpointer pObject, PairVec& vec) const noexcept = 0;
+ /**
+ * Retrieve the getter function depending on whether it's an auto-increment
+ * field, a QofClass getter, or a function passed to the constructor.
+ */
+ QofAccessFunc get_getter(QofIdTypeConst obj_name) const noexcept;
+ /**
+ * Retrieve the setter function depending on whether it's an auto-increment
+ * field, a QofClass getter, or a function passed to the constructor.
+ */
+ QofSetterFunc get_setter(QofIdTypeConst obj_name) const noexcept;
+ /**
+ * Retrieve the field name so that we don't need to make
+ * create_single_col_select_statement and friend.
+ */
+ const char* name() const noexcept { return m_col_name; }
+ /**
+ * Report if the entry is an auto-increment field.
+ */
+ bool is_autoincr() const noexcept { return m_flags & COL_AUTOINC; }
+ /* On the other hand, our implementation class and GncSqlColumnInfo need to
+ * be able to read our member variables.
+ */
+ template<GncSqlObjectType Otype> friend class GncSqlColumnTableEntryImpl;
+ friend struct GncSqlColumnInfo;
+ template<typename T> void load_from_guid_ref(GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject, T get_ref)
+ const noexcept
+ {
+ g_return_if_fail (pObject != NULL);
+
+ try
+ {
+ GncGUID guid;
+ auto val = row.get_string_at_col (m_col_name);
+ (void)string_to_guid (val.c_str(), &guid);
+ auto target = get_ref(&guid);
+ if (target != nullptr)
+ set_parameter (pObject, target, get_setter(obj_name),
+ m_gobj_param_name);
+ }
+ catch (std::invalid_argument) {}
+ }
+
+protected:
+ template <typename T> T
+ get_row_value_from_object(QofIdTypeConst obj_name, const gpointer pObject) const;
+ template <typename T> void
+ add_value_to_vec(const GncSqlBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, PairVec& vec) const;
+/**
+ * Adds a name/guid std::pair to a PairVec for creating a query.
+ *
+ * @param be SQL backend struct
+ * @param obj_name QOF object type name
+ * @param pObject Object
+ * @param pList List
+ */
+ void add_objectref_guid_to_query (const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept;
+/**
+ * Adds a column info structure for an object reference GncGUID to a ColVec.
+ *
+ * @param be SQL backend struct
+ * @param pList List
+ */
+ void add_objectref_guid_to_table (const GncSqlBackend* be,
+ ColVec& vec) const noexcept;
+private:
+ const char* m_col_name; /**< Column name */
+ const GncSqlObjectType m_col_type; /**< Column type */
+ unsigned int m_size; /**< Column size in bytes, for string columns */
+ ColumnFlags m_flags; /**< Column flags */
+ const char* m_gobj_param_name; /**< If non-null, g_object param name */
+ const char* m_qof_param_name; /**< If non-null, qof parameter name */
+ QofAccessFunc m_getter; /**< General access function */
+ QofSetterFunc m_setter; /**< General setter function */
+ template <typename T> T get_row_value_from_object(QofIdTypeConst obj_name,
+ const gpointer pObject,
+ std::true_type) const;
+ template <typename T> T get_row_value_from_object(QofIdTypeConst obj_name,
+ const gpointer pObject,
+ std::false_type) const;
+ template <typename T> void add_value_to_vec(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec, std::true_type) const;
+ template <typename T> void add_value_to_vec(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec, std::false_type) const;
+
+};
+
+template <GncSqlObjectType Type>
+class GncSqlColumnTableEntryImpl : public GncSqlColumnTableEntry
+{
+public:
+ GncSqlColumnTableEntryImpl (const char* name, const GncSqlObjectType type,
+ unsigned int s,
+ int f, const char* gobj_name = nullptr,
+ const char* qof_name = nullptr,
+ QofAccessFunc get = nullptr,
+ QofSetterFunc set = nullptr) :
+ GncSqlColumnTableEntry (name, type, s, f, gobj_name,qof_name, get, set)
+ {}
+ void load(const GncSqlBackend* be, GncSqlRow& row, QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept override;
+ void add_to_table(const GncSqlBackend* be, ColVec& vec) const noexcept override;
+ void add_to_query(const GncSqlBackend* be, QofIdTypeConst obj_name,
+ gpointer pObject, PairVec& vec) const noexcept override;
};
-inline bool operator==(const GncSqlColumnTableEntry& l,
- const GncSqlColumnTableEntry& r)
+template <GncSqlObjectType Type>
+std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
+gnc_sql_make_table_entry(const char* name, unsigned int s, int f)
{
- return strcmp(l.col_name, r.col_name) == 0 && l.col_type == r.col_type;
+ return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(name, Type, s, f);
}
-inline bool operator!=(const GncSqlColumnTableEntry& l,
- const GncSqlColumnTableEntry& r)
+template <GncSqlObjectType Type>
+std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
+gnc_sql_make_table_entry(const char* name, unsigned int s, int f,
+ const char* param)
{
- return !(l == r);
+ return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(name, Type, s,
+ f, param);
+}
+
+class is_qof : public std::true_type {};
+
+template <GncSqlObjectType Type>
+std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
+gnc_sql_make_table_entry(const char* name, unsigned int s, int f,
+ const char* param, bool qofp)
+{
+ return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(name, Type, s,
+ f, nullptr,
+ param);
+}
+
+template <GncSqlObjectType Type>
+std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
+gnc_sql_make_table_entry(const char* name, unsigned int s, int f,
+ QofAccessFunc get, QofSetterFunc set)
+{
+ return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(
+ name, Type, s, f, nullptr, nullptr, get, set);
}
/**
@@ -446,10 +589,10 @@ struct GncSqlColumnInfo
{}
GncSqlColumnInfo(const GncSqlColumnTableEntry& e, GncSqlBasicColumnType t,
unsigned int size = 0, bool unicode = true) :
- m_name{e.col_name}, m_type{t}, m_size{size}, m_unicode{unicode},
- m_autoinc(e.flags & COL_AUTOINC),
- m_primary_key(e.flags & COL_PKEY),
- m_not_null(e.flags & COL_NNUL) {}
+ m_name{e.m_col_name}, m_type{t}, m_size{size}, m_unicode{unicode},
+ m_autoinc(e.m_flags & COL_AUTOINC),
+ m_primary_key(e.m_flags & COL_PKEY),
+ m_not_null(e.m_flags & COL_NNUL) {}
std::string m_name; /**< Column name */
GncSqlBasicColumnType m_type; /**< Column basic type */
unsigned int m_size; /**< Column size (string types) */
@@ -478,18 +621,6 @@ typedef enum
OP_DB_DELETE
} E_DB_OPERATION;
-typedef void (*GNC_SQL_LOAD_FN) (const GncSqlBackend* be,
- GncSqlRow& row, QofSetterFunc setter,
- gpointer pObject,
- const GncSqlColumnTableEntry& table_row);
-typedef void (*GNC_SQL_ADD_COL_INFO_TO_LIST_FN) (const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec);
-typedef void (*GNC_SQL_ADD_VALUE_TO_VEC_FN) (const GncSqlBackend* be,
- QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec);
/**
* Set an object property with a setter function.
@@ -556,45 +687,6 @@ void set_parameter(T object, P item, F setter, const char* property)
}
/**
- * @struct GncSqlColumnTypeHandler
- *
- * The GncSqlColumnTypeHandler struct contains pointers to routines to handle
- * different options for a specific column type.
- *
- * A column type maps a property value to one or more columns in the database.
- */
-typedef struct
-{
- /**
- * Routine to load a value into an object from the database row.
- */
- GNC_SQL_LOAD_FN load_fn;
-
- /**
- * Routine to add a GncSqlColumnInfo structure for the column type to a
- * GList.
- */
- GNC_SQL_ADD_COL_INFO_TO_LIST_FN add_col_info_to_list_fn;
-
- /**
- * Add a pair of the table column heading and object's value's string
- * representation to a PairVec; used for constructing WHERE clauses and
- * UPDATE statements.
- */
- GNC_SQL_ADD_VALUE_TO_VEC_FN add_value_to_vec_fn;
-} GncSqlColumnTypeHandler;
-
-/**
- * Returns the QOF access function for a column.
- *
- * @param obj_name QOF object type name
- * @param table_row DB table column
- * @return Access function
- */
-QofAccessFunc gnc_sql_get_getter (QofIdTypeConst obj_name,
- const GncSqlColumnTableEntry& table_row);
-
-/**
* Performs an operation on the database.
*
* @param be SQL backend struct
@@ -769,42 +861,6 @@ GncSqlStatement* gnc_sql_create_select_statement (GncSqlBackend* be,
const gchar* table_name);
/**
- * Registers a column handler for a new column type.
- *
- * @param colType Column type
- * @param handler Column handler
- */
-void gnc_sql_register_col_type_handler (const GncSqlObjectType colType,
- const GncSqlColumnTypeHandler* handler);
-
-/**
- * Adds a GValue for an object reference GncGUID to the end of a GSList.
- *
- * @param be SQL backend struct
- * @param obj_name QOF object type name
- * @param pObject Object
- * @param table_row DB table column description
- * @param pList List
- */
-void gnc_sql_add_objectref_guid_to_vec (const GncSqlBackend* be,
- QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec);
-
-/**
- * Adds a column info structure for an object reference GncGUID to the end of a
- * GList.
- *
- * @param be SQL backend struct
- * @param table_row DB table column description
- * @param pList List
- */
-void gnc_sql_add_objectref_guid_col_info_to_list (const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec);
-
-/**
* Appends the ascii strings for a list of GUIDs to the end of an SQL string.
*
* @param str SQL string
@@ -910,25 +966,25 @@ typedef struct
} write_objects_t;
template <typename T> T
-get_row_value_from_object(QofIdTypeConst obj_name, const gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
+ const gpointer pObject) const
{
- return get_row_value_from_object<T>(obj_name, pObject, table_row,
+ return get_row_value_from_object<T>(obj_name, pObject,
std::is_pointer<T>());
}
template <typename T> T
-get_row_value_from_object(QofIdTypeConst obj_name, const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- std::true_type)
+GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
+ const gpointer pObject,
+ std::true_type) const
{
g_return_val_if_fail(obj_name != nullptr && pObject != nullptr, nullptr);
T result = nullptr;
- if (table_row.gobj_param_name != nullptr)
- g_object_get(pObject, table_row.gobj_param_name, &result, NULL );
+ if (m_gobj_param_name != nullptr)
+ g_object_get(pObject, m_gobj_param_name, &result, NULL );
else
{
- QofAccessFunc getter = gnc_sql_get_getter(obj_name, table_row);
+ QofAccessFunc getter = get_getter(obj_name);
if (getter != nullptr)
result = reinterpret_cast<T>((getter)(pObject, nullptr));
}
@@ -936,18 +992,18 @@ get_row_value_from_object(QofIdTypeConst obj_name, const gpointer pObject,
}
template <typename T> T
-get_row_value_from_object(QofIdTypeConst obj_name, const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- std::false_type)
+GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
+ const gpointer pObject,
+ std::false_type) const
{
g_return_val_if_fail(obj_name != nullptr && pObject != nullptr,
static_cast<T>(0));
T result = static_cast<T>(0);
- if (table_row.gobj_param_name != nullptr)
- g_object_get(pObject, table_row.gobj_param_name, &result, NULL );
+ if (m_gobj_param_name != nullptr)
+ g_object_get(pObject, m_gobj_param_name, &result, NULL );
else
{
- QofAccessFunc getter = gnc_sql_get_getter(obj_name, table_row);
+ QofAccessFunc getter = get_getter(obj_name);
if (getter != nullptr)
result = reinterpret_cast<T>((getter)(pObject, nullptr));
}
@@ -955,49 +1011,45 @@ get_row_value_from_object(QofIdTypeConst obj_name, const gpointer pObject,
}
template <typename T> void
-add_value_to_vec(const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
+GncSqlColumnTableEntry::add_value_to_vec(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const
{
- add_value_to_vec<T>(be, obj_name, pObject, table_row, vec,
- std::is_pointer<T>());
+ add_value_to_vec<T>(be, obj_name, pObject, vec, std::is_pointer<T>());
}
template <typename T> void
-add_value_to_vec(const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec, std::true_type)
+GncSqlColumnTableEntry::add_value_to_vec(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec, std::true_type) const
{
- T s = get_row_value_from_object<T>(obj_name, pObject, table_row);
+ T s = get_row_value_from_object<T>(obj_name, pObject);
if (s != nullptr)
{
std::ostringstream stream;
stream << *s;
- vec.emplace_back(std::make_pair(std::string{table_row.col_name},
- stream.str()));
+ vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
return;
}
}
template <typename T> void
-add_value_to_vec(const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec, std::false_type)
+GncSqlColumnTableEntry::add_value_to_vec(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec, std::false_type) const
{
- T s = get_row_value_from_object<T>(obj_name, pObject, table_row);
+ T s = get_row_value_from_object<T>(obj_name, pObject);
std::ostringstream stream;
stream << s;
- vec.emplace_back(std::make_pair(std::string{table_row.col_name},
- stream.str()));
+ vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
return;
}
-
#endif /* GNC_BACKEND_SQL_H */
/**
diff --git a/src/backend/sql/gnc-bill-term-sql.cpp b/src/backend/sql/gnc-bill-term-sql.cpp
index 44dcb41..718fec1 100644
--- a/src/backend/sql/gnc-bill-term-sql.cpp
+++ b/src/backend/sql/gnc-bill-term-sql.cpp
@@ -63,31 +63,36 @@ static void bt_set_parent_guid (gpointer data, gpointer value);
static EntryVec col_table
{
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "name", CT_STRING, MAX_NAME_LEN, COL_NNUL, "name" },
- { "description", CT_STRING, MAX_DESCRIPTION_LEN, COL_NNUL, NULL, GNC_BILLTERM_DESC },
- {
- "refcount", CT_INT, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)gncBillTermGetRefcount, (QofSetterFunc)gncBillTermSetRefcount
- },
- {
- "invisible", CT_BOOLEAN, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)gncBillTermGetInvisible, (QofSetterFunc)set_invisible
- },
- {
- "parent", CT_GUID, 0, 0, NULL, NULL,
- (QofAccessFunc)bt_get_parent, (QofSetterFunc)bt_set_parent
- },
- { "type", CT_STRING, MAX_TYPE_LEN, COL_NNUL, NULL, GNC_BILLTERM_TYPE },
- { "duedays", CT_INT, 0, 0, 0, GNC_BILLTERM_DUEDAYS },
- { "discountdays", CT_INT, 0, 0, 0, GNC_BILLTERM_DISCDAYS },
- { "discount", CT_NUMERIC, 0, 0, 0, GNC_BILLTERM_DISCOUNT },
- { "cutoff", CT_INT, 0, 0, 0, GNC_BILLTERM_CUTOFF },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_STRING>("name", MAX_NAME_LEN, COL_NNUL, "name"),
+ gnc_sql_make_table_entry<CT_STRING>("description", MAX_DESCRIPTION_LEN,
+ COL_NNUL, GNC_BILLTERM_DESC,
+ true),
+ gnc_sql_make_table_entry<CT_INT>("refcount", 0, COL_NNUL,
+ (QofAccessFunc)gncBillTermGetRefcount,
+ (QofSetterFunc)gncBillTermSetRefcount),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("invisible", 0, COL_NNUL,
+ (QofAccessFunc)gncBillTermGetInvisible,
+ (QofSetterFunc)set_invisible),
+ gnc_sql_make_table_entry<CT_GUID>("parent", 0, 0,
+ (QofAccessFunc)bt_get_parent,
+ (QofSetterFunc)bt_set_parent),
+ gnc_sql_make_table_entry<CT_STRING>("type", MAX_TYPE_LEN, COL_NNUL,
+ GNC_BILLTERM_TYPE, true),
+ gnc_sql_make_table_entry<CT_INT>("duedays", 0, 0, GNC_BILLTERM_DUEDAYS,
+ true),
+ gnc_sql_make_table_entry<CT_INT>("discountdays", 0, 0,
+ GNC_BILLTERM_DISCDAYS, true),
+ gnc_sql_make_table_entry<CT_NUMERIC>("discount", 0, 0,
+ GNC_BILLTERM_DISCOUNT, true),
+ gnc_sql_make_table_entry<CT_INT>("cutoff", 0, 0, GNC_BILLTERM_CUTOFF,
+ true),
};
static EntryVec billterm_parent_col_table
{
- { "parent", CT_GUID, 0, 0, NULL, NULL, NULL, (QofSetterFunc)bt_set_parent_guid },
+ gnc_sql_make_table_entry<CT_INT64>("parent", 0, 0, nullptr,
+ bt_set_parent_guid),
};
typedef struct
@@ -337,35 +342,34 @@ gnc_sql_save_billterm (GncSqlBackend* be, QofInstance* inst)
}
/* ================================================================= */
-static void
-load_billterm_guid (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
-{
- GncGUID guid;
- GncBillTerm* term = NULL;
- g_return_if_fail (be != NULL);
- g_return_if_fail (pObject != NULL);
+template<> void
+GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
+{
+ load_from_guid_ref(row, obj_name, pObject,
+ [be](GncGUID* g){
+ return gncBillTermLookup(be->book, g);
+ });
+}
- try
- {
- auto val = row.get_string_at_col (table_row.col_name);
- string_to_guid (val.c_str(), &guid);
- term = gncBillTermLookup (be->book, &guid);
- if (term != nullptr)
- set_parameter (pObject, term, setter, table_row.gobj_param_name);
- else
- PWARN ("Billterm ref '%s' not found", val.c_str());
- }
- catch (std::invalid_argument) {}
+template<> void
+GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
+{
+ add_objectref_guid_to_table(be, vec);
}
-static GncSqlColumnTypeHandler billterm_guid_handler
-= { load_billterm_guid,
- gnc_sql_add_objectref_guid_col_info_to_list,
- gnc_sql_add_objectref_guid_to_vec
- };
+template<> void
+GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
+{
+ add_objectref_guid_to_query(be, obj_name, pObject, vec);
+}
/* ================================================================= */
void
gnc_billterm_sql_initialize (void)
@@ -382,6 +386,5 @@ gnc_billterm_sql_initialize (void)
};
gnc_sql_register_backend(&be_data);
- gnc_sql_register_col_type_handler (CT_BILLTERMREF, &billterm_guid_handler);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-book-sql.cpp b/src/backend/sql/gnc-book-sql.cpp
index 0dabb42..ea30076 100644
--- a/src/backend/sql/gnc-book-sql.cpp
+++ b/src/backend/sql/gnc-book-sql.cpp
@@ -58,15 +58,14 @@ static void set_root_template_guid (gpointer pObject, gpointer pValue);
static const EntryVec col_table
{
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- {
- "root_account_guid", CT_GUID, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_root_account_guid, set_root_account_guid
- },
- {
- "root_template_guid", CT_GUID, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_root_template_guid, set_root_template_guid
- },
+ gnc_sql_make_table_entry<CT_GUID>(
+ "guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_GUID>("root_account_guid", 0, COL_NNUL,
+ (QofAccessFunc)get_root_account_guid,
+ set_root_account_guid),
+ gnc_sql_make_table_entry<CT_GUID>("root_template_guid", 0, COL_NNUL,
+ (QofAccessFunc)get_root_template_guid,
+ set_root_template_guid)
};
/* ================================================================= */
diff --git a/src/backend/sql/gnc-budget-sql.cpp b/src/backend/sql/gnc-budget-sql.cpp
index dad49c2..2318513 100644
--- a/src/backend/sql/gnc-budget-sql.cpp
+++ b/src/backend/sql/gnc-budget-sql.cpp
@@ -57,10 +57,14 @@ static QofLogModule log_module = G_LOG_DOMAIN;
static const EntryVec col_table
{
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "name", CT_STRING, BUDGET_MAX_NAME_LEN, COL_NNUL, "name" },
- { "description", CT_STRING, BUDGET_MAX_DESCRIPTION_LEN, 0, "description" },
- { "num_periods", CT_INT, 0, COL_NNUL, "num_periods" },
+ gnc_sql_make_table_entry<CT_GUID>(
+ "guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "name", BUDGET_MAX_NAME_LEN, COL_NNUL, "name"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "description", BUDGET_MAX_DESCRIPTION_LEN, 0, "description"),
+ gnc_sql_make_table_entry<CT_INT>(
+ "num_periods", 0, COL_NNUL, "num_periods"),
};
static QofInstance* get_budget (gpointer pObj);
@@ -81,23 +85,20 @@ typedef struct
static const EntryVec budget_amounts_col_table
{
- { "id", CT_INT, 0, COL_NNUL | COL_PKEY | COL_AUTOINC },
- {
- "budget_guid", CT_BUDGETREF, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_budget, (QofSetterFunc)set_budget
- },
- {
- "account_guid", CT_ACCOUNTREF, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_account, (QofSetterFunc)set_account
- },
- {
- "period_num", CT_INT, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_period_num, (QofSetterFunc)set_period_num
- },
- {
- "amount", CT_NUMERIC, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_amount, (QofSetterFunc)set_amount
- },
+ gnc_sql_make_table_entry<CT_INT>(
+ "id", 0, COL_NNUL | COL_PKEY | COL_AUTOINC),
+ gnc_sql_make_table_entry<CT_BUDGETREF>("budget_guid", 0, COL_NNUL,
+ (QofAccessFunc)get_budget,
+ (QofSetterFunc)set_budget),
+ gnc_sql_make_table_entry<CT_ACCOUNTREF>("account_guid", 0, COL_NNUL,
+ (QofAccessFunc)get_account,
+ (QofSetterFunc)set_account),
+ gnc_sql_make_table_entry<CT_INT>("period_num", 0, COL_NNUL,
+ (QofAccessFunc)get_period_num,
+ (QofSetterFunc)set_period_num),
+ gnc_sql_make_table_entry<CT_NUMERIC>("amount", 0, COL_NNUL,
+ (QofAccessFunc)get_amount,
+ (QofSetterFunc)set_amount),
};
/* ================================================================= */
@@ -460,36 +461,33 @@ write_budgets (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-load_budget_guid (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_BUDGETREF>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
- const GValue* val;
- GncGUID guid;
- GncBudget* budget = NULL;
-
- g_return_if_fail (be != NULL);
- g_return_if_fail (pObject != NULL);
+ load_from_guid_ref(row, obj_name, pObject,
+ [be](GncGUID* g){
+ return gnc_budget_lookup (g, be->book);
+ });
+}
- try
- {
- auto val = row.get_string_at_col (table_row.col_name);
- (void)string_to_guid (val.c_str(), &guid);
- budget = gnc_budget_lookup (&guid, be->book);
- if (budget != nullptr)
- set_parameter(pObject, budget, setter, table_row.gobj_param_name);
- else
- PWARN ("Budget ref '%s' not found", val.c_str());
- }
- catch (std::invalid_argument) {}
+template<> void
+GncSqlColumnTableEntryImpl<CT_BUDGETREF>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
+{
+ add_objectref_guid_to_table(be, vec);
}
-static GncSqlColumnTypeHandler budget_guid_handler
-= { load_budget_guid,
- gnc_sql_add_objectref_guid_col_info_to_list,
- gnc_sql_add_objectref_guid_to_vec
- };
+template<> void
+GncSqlColumnTableEntryImpl<CT_BUDGETREF>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
+{
+ add_objectref_guid_to_query(be, obj_name, pObject, vec);
+}
/* ================================================================= */
void
gnc_sql_init_budget_handler (void)
@@ -508,6 +506,5 @@ gnc_sql_init_budget_handler (void)
};
gnc_sql_register_backend(&be_data);
- gnc_sql_register_col_type_handler (CT_BUDGETREF, &budget_guid_handler);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-commodity-sql.cpp b/src/backend/sql/gnc-commodity-sql.cpp
index 331ffdd..82c2972 100644
--- a/src/backend/sql/gnc-commodity-sql.cpp
+++ b/src/backend/sql/gnc-commodity-sql.cpp
@@ -61,22 +61,27 @@ static void set_quote_source_name (gpointer pObject, gpointer pValue);
static const EntryVec col_table
{
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- {
- "namespace", CT_STRING, COMMODITY_MAX_NAMESPACE_LEN, COL_NNUL, NULL, NULL,
- (QofAccessFunc)gnc_commodity_get_namespace,
- (QofSetterFunc)gnc_commodity_set_namespace
- },
- { "mnemonic", CT_STRING, COMMODITY_MAX_MNEMONIC_LEN, COL_NNUL, "mnemonic" },
- { "fullname", CT_STRING, COMMODITY_MAX_FULLNAME_LEN, 0, "fullname" },
- { "cusip", CT_STRING, COMMODITY_MAX_CUSIP_LEN, 0, "cusip" },
- { "fraction", CT_INT, 0, COL_NNUL, "fraction" },
- { "quote_flag", CT_BOOLEAN, 0, COL_NNUL, "quote_flag" },
- {
- "quote_source", CT_STRING, COMMODITY_MAX_QUOTESOURCE_LEN, 0, NULL, NULL,
- (QofAccessFunc)get_quote_source_name, set_quote_source_name
- },
- { "quote_tz", CT_STRING, COMMODITY_MAX_QUOTE_TZ_LEN, 0, "quote-tz" },
+ gnc_sql_make_table_entry<CT_GUID>(
+ "guid", 0, COL_NNUL | COL_PKEY | COL_UNIQUE, "guid"),
+ gnc_sql_make_table_entry<CT_STRING>("namespace",
+ COMMODITY_MAX_NAMESPACE_LEN, COL_NNUL,
+ (QofAccessFunc)gnc_commodity_get_namespace,
+ (QofSetterFunc)gnc_commodity_set_namespace),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "mnemonic", COMMODITY_MAX_MNEMONIC_LEN, COL_NNUL, "mnemonic"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "fullname", COMMODITY_MAX_FULLNAME_LEN, 0, "fullname"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "cusip", COMMODITY_MAX_CUSIP_LEN, 0, "cusip"),
+ gnc_sql_make_table_entry<CT_INT>("fraction", 0, COL_NNUL, "fraction"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>(
+ "quote_flag", 0, COL_NNUL, "quote_flag"),
+ gnc_sql_make_table_entry<CT_STRING>("quote_source",
+ COMMODITY_MAX_QUOTESOURCE_LEN, 0,
+ (QofAccessFunc)get_quote_source_name,
+ set_quote_source_name),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "quote_tz", COMMODITY_MAX_QUOTE_TZ_LEN, 0, "quote-tz"),
};
/* ================================================================= */
@@ -262,37 +267,33 @@ gnc_sql_commit_commodity (gnc_commodity* pCommodity)
}
/* ----------------------------------------------------------------- */
-
-static void
-load_commodity_guid (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_COMMODITYREF>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
- GncGUID guid;
- gnc_commodity* commodity = NULL;
-
- g_return_if_fail (be != NULL);
- g_return_if_fail (pObject != NULL);
+ load_from_guid_ref(row, obj_name, pObject,
+ [be](GncGUID* g){
+ return gnc_commodity_find_commodity_by_guid(g, be->book);
+ });
+}
- try
- {
- auto val = row.get_string_at_col (table_row.col_name);
- (void)string_to_guid (val.c_str(), &guid);
- commodity = gnc_commodity_find_commodity_by_guid (&guid, be->book);
- if (commodity != nullptr)
- set_parameter (pObject, commodity, setter,
- table_row.gobj_param_name);
- else
- PWARN ("Commodity ref '%s' not found", val.c_str());
- }
- catch (std::invalid_argument) {}
+template<> void
+GncSqlColumnTableEntryImpl<CT_COMMODITYREF>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
+{
+ add_objectref_guid_to_table(be, vec);
}
-static GncSqlColumnTypeHandler commodity_guid_handler
-= { load_commodity_guid,
- gnc_sql_add_objectref_guid_col_info_to_list,
- gnc_sql_add_objectref_guid_to_vec
- };
+template<> void
+GncSqlColumnTableEntryImpl<CT_COMMODITYREF>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
+{
+ add_objectref_guid_to_query(be, obj_name, pObject, vec);
+}
/* ================================================================= */
void
gnc_sql_init_commodity_handler (void)
@@ -311,6 +312,5 @@ gnc_sql_init_commodity_handler (void)
};
gnc_sql_register_backend(&be_data);
- gnc_sql_register_col_type_handler (CT_COMMODITYREF, &commodity_guid_handler);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-customer-sql.cpp b/src/backend/sql/gnc-customer-sql.cpp
index 631917d..583629f 100644
--- a/src/backend/sql/gnc-customer-sql.cpp
+++ b/src/backend/sql/gnc-customer-sql.cpp
@@ -43,7 +43,6 @@ extern "C"
#include "gnc-backend-sql.h"
#include "gnc-slots-sql.h"
#include "gnc-customer-sql.h"
-#include "gnc-address-sql.h"
#include "gnc-bill-term-sql.h"
#include "gnc-tax-table-sql.h"
@@ -60,29 +59,35 @@ static QofLogModule log_module = G_LOG_DOMAIN;
static EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "name", CT_STRING, MAX_NAME_LEN, COL_NNUL, "name" },
- { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, CUSTOMER_ID },
- { "notes", CT_STRING, MAX_NOTES_LEN, COL_NNUL, NULL, CUSTOMER_NOTES },
- { "active", CT_BOOLEAN, 0, COL_NNUL, NULL, QOF_PARAM_ACTIVE },
- { "discount", CT_NUMERIC, 0, COL_NNUL, NULL, CUSTOMER_DISCOUNT },
- { "credit", CT_NUMERIC, 0, COL_NNUL, NULL, CUSTOMER_CREDIT },
- {
- "currency", CT_COMMODITYREF, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)gncCustomerGetCurrency, (QofSetterFunc)gncCustomerSetCurrency
- },
- { "tax_override", CT_BOOLEAN, 0, COL_NNUL, NULL, CUSTOMER_TT_OVER },
- { "addr", CT_ADDRESS, 0, 0, NULL, CUSTOMER_ADDR },
- { "shipaddr", CT_ADDRESS, 0, 0, NULL, CUSTOMER_SHIPADDR },
- { "terms", CT_BILLTERMREF, 0, 0, NULL, CUSTOMER_TERMS },
- {
- "tax_included", CT_INT, 0, 0, NULL, NULL,
- (QofAccessFunc)gncCustomerGetTaxIncluded, (QofSetterFunc)gncCustomerSetTaxIncluded
- },
- {
- "taxtable", CT_TAXTABLEREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncCustomerGetTaxTable, (QofSetterFunc)gncCustomerSetTaxTable
- },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid" ),
+ gnc_sql_make_table_entry<CT_STRING>("name", MAX_NAME_LEN, COL_NNUL, "name"),
+ gnc_sql_make_table_entry<CT_STRING>("id", MAX_ID_LEN, COL_NNUL,
+ CUSTOMER_ID, true),
+ gnc_sql_make_table_entry<CT_STRING>("notes", MAX_NOTES_LEN, COL_NNUL,
+ CUSTOMER_NOTES, true),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("active", 0, COL_NNUL,
+ QOF_PARAM_ACTIVE, true),
+ gnc_sql_make_table_entry<CT_NUMERIC>("discount", 0, COL_NNUL,
+ CUSTOMER_DISCOUNT, true),
+ gnc_sql_make_table_entry<CT_NUMERIC>("credit", 0, COL_NNUL,
+ CUSTOMER_CREDIT, true),
+ gnc_sql_make_table_entry<CT_COMMODITYREF>("currency", 0, COL_NNUL,
+ (QofAccessFunc)gncCustomerGetCurrency,
+ (QofSetterFunc)gncCustomerSetCurrency),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("tax_override", 0, COL_NNUL,
+ CUSTOMER_TT_OVER, true),
+ gnc_sql_make_table_entry<CT_ADDRESS>("addr", 0, 0, CUSTOMER_ADDR,
+ true),
+ gnc_sql_make_table_entry<CT_ADDRESS>("shipaddr", 0, 0, CUSTOMER_SHIPADDR,
+ true),
+ gnc_sql_make_table_entry<CT_BILLTERMREF>("terms", 0, 0, CUSTOMER_TERMS,
+ true),
+ gnc_sql_make_table_entry<CT_INT>("tax_included", 0, 0,
+ (QofAccessFunc)gncCustomerGetTaxIncluded,
+ (QofSetterFunc)gncCustomerSetTaxIncluded),
+ gnc_sql_make_table_entry<CT_TAXTABLEREF>("taxtable", 0, 0,
+ (QofAccessFunc)gncCustomerGetTaxTable,
+ (QofSetterFunc)gncCustomerSetTaxTable),
});
static GncCustomer*
diff --git a/src/backend/sql/gnc-employee-sql.cpp b/src/backend/sql/gnc-employee-sql.cpp
index c0ed579..20e2df7 100644
--- a/src/backend/sql/gnc-employee-sql.cpp
+++ b/src/backend/sql/gnc-employee-sql.cpp
@@ -43,8 +43,6 @@ extern "C"
#include "gnc-slots-sql.h"
#include "gnc-commodity-sql.h"
#include "gnc-employee-sql.h"
-#include "gnc-address-sql.h"
-
#define _GNC_MOD_NAME GNC_ID_EMPLOYEE
@@ -60,17 +58,21 @@ static QofLogModule log_module = G_LOG_DOMAIN;
static EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "username", CT_STRING, MAX_USERNAME_LEN, COL_NNUL, "username" },
- { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, "id" },
- { "language", CT_STRING, MAX_LANGUAGE_LEN, COL_NNUL, "language" },
- { "acl", CT_STRING, MAX_ACL_LEN, COL_NNUL, "acl" },
- { "active", CT_BOOLEAN, 0, COL_NNUL, "active" },
- { "currency", CT_COMMODITYREF, 0, COL_NNUL, "currency" },
- { "ccard_guid", CT_ACCOUNTREF, 0, 0, "credit-card-account" },
- { "workday", CT_NUMERIC, 0, COL_NNUL, "workday" },
- { "rate", CT_NUMERIC, 0, COL_NNUL, "rate" },
- { "addr", CT_ADDRESS, 0, 0, "address" },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "username", MAX_USERNAME_LEN, COL_NNUL, "username"),
+ gnc_sql_make_table_entry<CT_STRING>("id", MAX_ID_LEN, COL_NNUL, "id"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "language", MAX_LANGUAGE_LEN, COL_NNUL, "language"),
+ gnc_sql_make_table_entry<CT_STRING>("acl", MAX_ACL_LEN, COL_NNUL, "acl"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("active", 0, COL_NNUL, "active"),
+ gnc_sql_make_table_entry<CT_COMMODITYREF>(
+ "currency", 0, COL_NNUL, "currency"),
+ gnc_sql_make_table_entry<CT_ACCOUNTREF>(
+ "ccard_guid", 0, 0, "credit-card-account"),
+ gnc_sql_make_table_entry<CT_NUMERIC>("workday", 0, COL_NNUL, "workday"),
+ gnc_sql_make_table_entry<CT_NUMERIC>("rate", 0, COL_NNUL, "rate"),
+ gnc_sql_make_table_entry<CT_ADDRESS>("addr", 0, 0, "address"),
});
static GncEmployee*
diff --git a/src/backend/sql/gnc-entry-sql.cpp b/src/backend/sql/gnc-entry-sql.cpp
index fbf84a2..59b6bf8 100644
--- a/src/backend/sql/gnc-entry-sql.cpp
+++ b/src/backend/sql/gnc-entry-sql.cpp
@@ -46,7 +46,6 @@ extern "C"
#include "gnc-entry-sql.h"
#include "gnc-invoice-sql.h"
#include "gnc-order-sql.h"
-#include "gnc-owner-sql.h"
#include "gnc-tax-table-sql.h"
#define _GNC_MOD_NAME GNC_ID_ENTRY
@@ -66,53 +65,63 @@ static void entry_set_bill (gpointer pObject, gpointer val);
static EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "date", CT_TIMESPEC, 0, COL_NNUL, NULL, ENTRY_DATE },
- { "date_entered", CT_TIMESPEC, 0, 0, NULL, ENTRY_DATE_ENTERED },
- { "description", CT_STRING, MAX_DESCRIPTION_LEN, 0, "description" },
- { "action", CT_STRING, MAX_ACTION_LEN, 0, NULL, ENTRY_ACTION },
- { "notes", CT_STRING, MAX_NOTES_LEN, 0, NULL, ENTRY_NOTES },
- { "quantity", CT_NUMERIC, 0, 0, NULL, ENTRY_QTY },
- { "i_acct", CT_ACCOUNTREF, 0, 0, NULL, ENTRY_IACCT },
- { "i_price", CT_NUMERIC, 0, 0, NULL, ENTRY_IPRICE },
- {
- "i_discount", CT_NUMERIC, 0, 0, NULL, NULL,
- (QofAccessFunc)gncEntryGetInvDiscount, (QofSetterFunc)gncEntrySetInvDiscount
- },
- {
- "invoice", CT_INVOICEREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncEntryGetInvoice, (QofSetterFunc)entry_set_invoice
- },
- { "i_disc_type", CT_STRING, MAX_DISCTYPE_LEN, 0, NULL, ENTRY_INV_DISC_TYPE },
- { "i_disc_how", CT_STRING, MAX_DISCHOW_LEN, 0, NULL, ENTRY_INV_DISC_HOW },
- { "i_taxable", CT_BOOLEAN, 0, 0, NULL, ENTRY_INV_TAXABLE },
- { "i_taxincluded", CT_BOOLEAN, 0, 0, NULL, ENTRY_INV_TAX_INC },
- {
- "i_taxtable", CT_TAXTABLEREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncEntryGetInvTaxTable, (QofSetterFunc)gncEntrySetInvTaxTable
- },
- { "b_acct", CT_ACCOUNTREF, 0, 0, NULL, ENTRY_BACCT },
- { "b_price", CT_NUMERIC, 0, 0, NULL, ENTRY_BPRICE },
- {
- "bill", CT_INVOICEREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncEntryGetBill, (QofSetterFunc)entry_set_bill
- },
- { "b_taxable", CT_BOOLEAN, 0, 0, NULL, ENTRY_BILL_TAXABLE },
- { "b_taxincluded", CT_BOOLEAN, 0, 0, NULL, ENTRY_BILL_TAX_INC },
- {
- "b_taxtable", CT_TAXTABLEREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncEntryGetBillTaxTable, (QofSetterFunc)gncEntrySetBillTaxTable
- },
- {
- "b_paytype", CT_INT, 0, 0, NULL, NULL,
- (QofAccessFunc)gncEntryGetBillPayment, (QofSetterFunc)gncEntrySetBillPayment
- },
- { "billable", CT_BOOLEAN, 0, 0, NULL, ENTRY_BILLABLE },
- { "billto", CT_OWNERREF, 0, 0, NULL, ENTRY_BILLTO },
- {
- "order_guid", CT_ORDERREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncEntryGetOrder, (QofSetterFunc)gncEntrySetOrder
- },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_TIMESPEC>("date", 0, COL_NNUL, ENTRY_DATE,
+ true),
+ gnc_sql_make_table_entry<CT_TIMESPEC>("date_entered", 0, 0,
+ ENTRY_DATE_ENTERED, true),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "description", MAX_DESCRIPTION_LEN, 0, "description"),
+ gnc_sql_make_table_entry<CT_STRING>("action", MAX_ACTION_LEN, 0,
+ ENTRY_ACTION, true),
+ gnc_sql_make_table_entry<CT_STRING>("notes", MAX_NOTES_LEN, 0, ENTRY_NOTES,
+ true),
+ gnc_sql_make_table_entry<CT_NUMERIC>("quantity", 0, 0, ENTRY_QTY,
+ true),
+ gnc_sql_make_table_entry<CT_ACCOUNTREF>("i_acct", 0, 0, ENTRY_IACCT,
+ true),
+ gnc_sql_make_table_entry<CT_NUMERIC>("i_price", 0, 0, ENTRY_IPRICE,
+ true),
+ gnc_sql_make_table_entry<CT_NUMERIC>("i_discount", 0, 0,
+ (QofAccessFunc)gncEntryGetInvDiscount,
+ (QofSetterFunc)gncEntrySetInvDiscount),
+ gnc_sql_make_table_entry<CT_INVOICEREF>("invoice", 0, 0,
+ (QofAccessFunc)gncEntryGetInvoice,
+ (QofSetterFunc)entry_set_invoice),
+ gnc_sql_make_table_entry<CT_STRING>("i_disc_type", MAX_DISCTYPE_LEN, 0,
+ ENTRY_INV_DISC_TYPE, true),
+ gnc_sql_make_table_entry<CT_STRING>("i_disc_how", MAX_DISCHOW_LEN, 0,
+ ENTRY_INV_DISC_HOW, true),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("i_taxable", 0, 0, ENTRY_INV_TAXABLE,
+ true),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("i_taxincluded", 0, 0,
+ ENTRY_INV_TAX_INC, true),
+ gnc_sql_make_table_entry<CT_TAXTABLEREF>("i_taxtable", 0, 0,
+ (QofAccessFunc)gncEntryGetInvTaxTable,
+ (QofSetterFunc)gncEntrySetInvTaxTable),
+ gnc_sql_make_table_entry<CT_ACCOUNTREF>("b_acct", 0, 0, ENTRY_BACCT,
+ true),
+ gnc_sql_make_table_entry<CT_NUMERIC>("b_price", 0, 0, ENTRY_BPRICE,
+ true),
+ gnc_sql_make_table_entry<CT_INVOICEREF>("bill", 0, 0,
+ (QofAccessFunc)gncEntryGetBill,
+ (QofSetterFunc)entry_set_bill),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("b_taxable", 0, 0, ENTRY_BILL_TAXABLE,
+ true),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("b_taxincluded", 0, 0,
+ ENTRY_BILL_TAX_INC, true),
+ gnc_sql_make_table_entry<CT_TAXTABLEREF>("b_taxtable", 0, 0,
+ (QofAccessFunc)gncEntryGetBillTaxTable,
+ (QofSetterFunc)gncEntrySetBillTaxTable),
+ gnc_sql_make_table_entry<CT_INT>("b_paytype", 0, 0,
+ (QofAccessFunc)gncEntryGetBillPayment,
+ (QofSetterFunc)gncEntrySetBillPayment),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("billable", 0, 0, ENTRY_BILLABLE,
+ true),
+ gnc_sql_make_table_entry<CT_OWNERREF>("billto", 0, 0, ENTRY_BILLTO, true),
+ gnc_sql_make_table_entry<CT_ORDERREF>("order_guid", 0, 0,
+ (QofAccessFunc)gncEntryGetOrder,
+ (QofSetterFunc)gncEntrySetOrder),
});
static void
diff --git a/src/backend/sql/gnc-invoice-sql.cpp b/src/backend/sql/gnc-invoice-sql.cpp
index 819538c..fd8450d 100644
--- a/src/backend/sql/gnc-invoice-sql.cpp
+++ b/src/backend/sql/gnc-invoice-sql.cpp
@@ -45,7 +45,6 @@ extern "C"
#include "gnc-commodity-sql.h"
#include "gnc-slots-sql.h"
#include "gnc-invoice-sql.h"
-#include "gnc-owner-sql.h"
#include "gnc-bill-term-sql.h"
#define _GNC_MOD_NAME GNC_ID_INVOICE
@@ -61,36 +60,40 @@ static QofLogModule log_module = G_LOG_DOMAIN;
static EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, INVOICE_ID },
- { "date_opened", CT_TIMESPEC, 0, 0, NULL, INVOICE_OPENED },
- { "date_posted", CT_TIMESPEC, 0, 0, NULL, INVOICE_POSTED },
- { "notes", CT_STRING, MAX_NOTES_LEN, COL_NNUL, "notes" },
- { "active", CT_BOOLEAN, 0, COL_NNUL, NULL, QOF_PARAM_ACTIVE },
- {
- "currency", CT_COMMODITYREF, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)gncInvoiceGetCurrency, (QofSetterFunc)gncInvoiceSetCurrency
- },
- {
- "owner", CT_OWNERREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncInvoiceGetOwner, (QofSetterFunc)gncInvoiceSetOwner
- },
- { "terms", CT_BILLTERMREF, 0, 0, NULL, INVOICE_TERMS },
- { "billing_id", CT_STRING, MAX_BILLING_ID_LEN, 0, NULL, INVOICE_BILLINGID },
- { "post_txn", CT_TXREF, 0, 0, NULL, INVOICE_POST_TXN },
- {
- "post_lot", CT_LOTREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncInvoiceGetPostedLot, (QofSetterFunc)gncInvoiceSetPostedLot
- },
- { "post_acc", CT_ACCOUNTREF, 0, 0, NULL, INVOICE_ACC },
- {
- "billto", CT_OWNERREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncInvoiceGetBillTo, (QofSetterFunc)gncInvoiceSetBillTo
- },
- {
- "charge_amt", CT_NUMERIC, 0, 0, NULL, NULL,
- (QofAccessFunc)gncInvoiceGetToChargeAmount, (QofSetterFunc)gncInvoiceSetToChargeAmount
- },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_STRING>("id", MAX_ID_LEN, COL_NNUL, INVOICE_ID,
+ true),
+ gnc_sql_make_table_entry<CT_TIMESPEC>("date_opened", 0, 0, INVOICE_OPENED,
+ true),
+ gnc_sql_make_table_entry<CT_TIMESPEC>("date_posted", 0, 0, INVOICE_POSTED,
+ true),
+ gnc_sql_make_table_entry<CT_STRING>("notes", MAX_NOTES_LEN, COL_NNUL,
+ "notes"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("active", 0, COL_NNUL,
+ QOF_PARAM_ACTIVE, true),
+ gnc_sql_make_table_entry<CT_COMMODITYREF>("currency", 0, COL_NNUL,
+ (QofAccessFunc)gncInvoiceGetCurrency,
+ (QofSetterFunc)gncInvoiceSetCurrency),
+ gnc_sql_make_table_entry<CT_OWNERREF>("owner", 0, 0,
+ (QofAccessFunc)gncInvoiceGetOwner,
+ (QofSetterFunc)gncInvoiceSetOwner),
+ gnc_sql_make_table_entry<CT_BILLTERMREF>("terms", 0, 0, INVOICE_TERMS,
+ true),
+ gnc_sql_make_table_entry<CT_STRING>("billing_id", MAX_BILLING_ID_LEN, 0,
+ INVOICE_BILLINGID, true),
+ gnc_sql_make_table_entry<CT_TXREF>("post_txn", 0, 0, INVOICE_POST_TXN,
+ true),
+ gnc_sql_make_table_entry<CT_LOTREF>("post_lot", 0, 0,
+ (QofAccessFunc)gncInvoiceGetPostedLot,
+ (QofSetterFunc)gncInvoiceSetPostedLot),
+ gnc_sql_make_table_entry<CT_ACCOUNTREF>("post_acc", 0, 0, INVOICE_ACC,
+ true),
+ gnc_sql_make_table_entry<CT_OWNERREF>("billto", 0, 0,
+ (QofAccessFunc)gncInvoiceGetBillTo,
+ (QofSetterFunc)gncInvoiceSetBillTo),
+ gnc_sql_make_table_entry<CT_NUMERIC>("charge_amt", 0, 0,
+ (QofAccessFunc)gncInvoiceGetToChargeAmount,
+ (QofSetterFunc)gncInvoiceSetToChargeAmount),
});
static GncInvoice*
@@ -274,35 +277,34 @@ write_invoices (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-load_invoice_guid (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_INVOICEREF>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
- GncGUID guid;
- GncInvoice* invoice = NULL;
+ load_from_guid_ref(row, obj_name, pObject,
+ [be](GncGUID* g){
+ return gncInvoiceLookup (be->book, g);
+ });
+}
- g_return_if_fail (be != NULL);
- g_return_if_fail (pObject != NULL);
+template<> void
+GncSqlColumnTableEntryImpl<CT_INVOICEREF>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
+{
+ add_objectref_guid_to_table(be, vec);
+}
- try
- {
- auto val = row.get_string_at_col (table_row.col_name);
- string_to_guid (val.c_str(), &guid);
- invoice = gncInvoiceLookup (be->book, &guid);
- if (invoice != nullptr)
- set_parameter (pObject, invoice, setter, table_row.gobj_param_name);
- else
- PWARN ("Invoice ref '%s' not found", val.c_str());
- }
- catch (std::invalid_argument) {}
+template<> void
+GncSqlColumnTableEntryImpl<CT_INVOICEREF>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
+{
+ add_objectref_guid_to_query(be, obj_name, pObject, vec);
}
-static GncSqlColumnTypeHandler invoice_guid_handler
-= { load_invoice_guid,
- gnc_sql_add_objectref_guid_col_info_to_list,
- gnc_sql_add_objectref_guid_to_vec
- };
/* ================================================================= */
void
gnc_invoice_sql_initialize (void)
@@ -319,6 +321,5 @@ gnc_invoice_sql_initialize (void)
};
gnc_sql_register_backend(&be_data);
- gnc_sql_register_col_type_handler (CT_INVOICEREF, &invoice_guid_handler);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-job-sql.cpp b/src/backend/sql/gnc-job-sql.cpp
index 932f51c..b57a867 100644
--- a/src/backend/sql/gnc-job-sql.cpp
+++ b/src/backend/sql/gnc-job-sql.cpp
@@ -41,7 +41,6 @@ extern "C"
#include "gnc-backend-sql.h"
#include "gnc-slots-sql.h"
#include "gnc-job-sql.h"
-#include "gnc-owner-sql.h"
#define _GNC_MOD_NAME GNC_ID_JOB
@@ -56,18 +55,18 @@ G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
static EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, JOB_ID },
- { "name", CT_STRING, MAX_NAME_LEN, COL_NNUL, "name" },
- { "reference", CT_STRING, MAX_REFERENCE_LEN, COL_NNUL, NULL, JOB_REFERENCE },
- {
- "active", CT_BOOLEAN, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)gncJobGetActive, (QofSetterFunc)gncJobSetActive
- },
- {
- "owner", CT_OWNERREF, 0, 0, NULL, NULL,
- (QofAccessFunc)gncJobGetOwner, (QofSetterFunc)gncJobSetOwner
- },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_STRING>("id", MAX_ID_LEN, COL_NNUL,
+ JOB_ID, true),
+ gnc_sql_make_table_entry<CT_STRING>("name", MAX_NAME_LEN, COL_NNUL, "name"),
+ gnc_sql_make_table_entry<CT_STRING>("reference", MAX_REFERENCE_LEN,
+ COL_NNUL, JOB_REFERENCE, true),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("active", 0, COL_NNUL,
+ (QofAccessFunc)gncJobGetActive,
+ (QofSetterFunc)gncJobSetActive),
+ gnc_sql_make_table_entry<CT_OWNERREF>("owner", 0, 0,
+ (QofAccessFunc)gncJobGetOwner,
+ (QofSetterFunc)gncJobSetOwner),
});
static GncJob*
diff --git a/src/backend/sql/gnc-lots-sql.cpp b/src/backend/sql/gnc-lots-sql.cpp
index 59fd241..42dfd9e 100644
--- a/src/backend/sql/gnc-lots-sql.cpp
+++ b/src/backend/sql/gnc-lots-sql.cpp
@@ -56,12 +56,11 @@ static void set_lot_account (gpointer pObject, gpointer pValue);
static const EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- {
- "account_guid", CT_ACCOUNTREF, 0, 0, NULL, NULL,
- (QofAccessFunc)get_lot_account, set_lot_account
- },
- { "is_closed", CT_BOOLEAN, 0, COL_NNUL, "is-closed" }
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_ACCOUNTREF>("account_guid", 0, 0,
+ (QofAccessFunc)get_lot_account,
+ set_lot_account),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("is_closed", 0, COL_NNUL, "is-closed")
});
/* ================================================================= */
@@ -203,35 +202,33 @@ write_lots (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-load_lot_guid (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_LOTREF>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
- GncGUID guid;
- GNCLot* lot;
-
- g_return_if_fail (be != NULL);
- g_return_if_fail (pObject != NULL);
+ load_from_guid_ref(row, obj_name, pObject,
+ [be](GncGUID* g){
+ return gnc_lot_lookup(g, be->book);
+ });
+}
- try
- {
- auto val = row.get_string_at_col (table_row.col_name);
- (void)string_to_guid (val.c_str(), &guid);
- lot = gnc_lot_lookup (&guid, be->book);
- if (lot != nullptr)
- set_parameter (pObject, lot, setter, table_row.gobj_param_name);
- else
- PWARN ("Lot ref '%s' not found", val.c_str());
- }
- catch (std::invalid_argument) {}
+template<> void
+GncSqlColumnTableEntryImpl<CT_LOTREF>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
+{
+ add_objectref_guid_to_table(be, vec);
}
-static GncSqlColumnTypeHandler lot_guid_handler
-= { load_lot_guid,
- gnc_sql_add_objectref_guid_col_info_to_list,
- gnc_sql_add_objectref_guid_to_vec
- };
+template<> void
+GncSqlColumnTableEntryImpl<CT_LOTREF>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
+{
+ add_objectref_guid_to_query(be, obj_name, pObject, vec);
+}
/* ================================================================= */
void
gnc_sql_init_lot_handler (void)
@@ -248,7 +245,6 @@ gnc_sql_init_lot_handler (void)
};
gnc_sql_register_backend(&be_data);
- gnc_sql_register_col_type_handler (CT_LOTREF, &lot_guid_handler);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-order-sql.cpp b/src/backend/sql/gnc-order-sql.cpp
index 8367797..d931eb7 100644
--- a/src/backend/sql/gnc-order-sql.cpp
+++ b/src/backend/sql/gnc-order-sql.cpp
@@ -41,7 +41,6 @@ extern "C"
#include "gnc-backend-sql.h"
#include "gnc-slots-sql.h"
#include "gnc-order-sql.h"
-#include "gnc-owner-sql.h"
#define _GNC_MOD_NAME GNC_ID_ORDER
@@ -56,14 +55,19 @@ static QofLogModule log_module = G_LOG_DOMAIN;
static EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, "id" },
- { "notes", CT_STRING, MAX_NOTES_LEN, COL_NNUL, "notes" },
- { "reference", CT_STRING, MAX_REFERENCE_LEN, COL_NNUL, "reference" },
- { "active", CT_BOOLEAN, 0, COL_NNUL, "order" },
- { "date_opened", CT_TIMESPEC, 0, COL_NNUL, "date-opened" },
- { "date_closed", CT_TIMESPEC, 0, COL_NNUL, "date-closed" },
- { "owner", CT_OWNERREF, 0, COL_NNUL, NULL, ORDER_OWNER },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_STRING>("id", MAX_ID_LEN, COL_NNUL, "id"),
+ gnc_sql_make_table_entry<CT_STRING>("notes", MAX_NOTES_LEN, COL_NNUL,
+ "notes"),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "reference", MAX_REFERENCE_LEN, COL_NNUL, "reference"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("active", 0, COL_NNUL, "order"),
+ gnc_sql_make_table_entry<CT_TIMESPEC>("date_opened", 0, COL_NNUL,
+ "date-opened"),
+ gnc_sql_make_table_entry<CT_TIMESPEC>("date_closed", 0, COL_NNUL,
+ "date-closed"),
+ gnc_sql_make_table_entry<CT_OWNERREF>("owner", 0, COL_NNUL,
+ ORDER_OWNER, true),
});
static GncOrder*
@@ -188,35 +192,33 @@ write_orders (GncSqlBackend* be)
}
/* ================================================================= */
-static void
-load_order_guid (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_ORDERREF>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
- GncGUID guid;
- GncOrder* order = NULL;
-
- g_return_if_fail (be != NULL);
- g_return_if_fail (pObject != NULL);
+ load_from_guid_ref(row, obj_name, pObject,
+ [be](GncGUID* g){
+ return gncOrderLookup(be->book, g);
+ });
+}
- try
- {
- auto val = row.get_string_at_col (table_row.col_name);
- string_to_guid (val.c_str(), &guid);
- order = gncOrderLookup (be->book, &guid);
- if (order != nullptr)
- set_parameter (pObject, order, setter, table_row.gobj_param_name);
- else
- PWARN ("Order ref '%s' not found", val.c_str());
- }
- catch (std::invalid_argument) {}
+template<> void
+GncSqlColumnTableEntryImpl<CT_ORDERREF>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
+{
+ add_objectref_guid_to_table(be, vec);
}
-static GncSqlColumnTypeHandler order_guid_handler
-= { load_order_guid,
- gnc_sql_add_objectref_guid_col_info_to_list,
- gnc_sql_add_objectref_guid_to_vec
- };
+template<> void
+GncSqlColumnTableEntryImpl<CT_ORDERREF>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
+{
+ add_objectref_guid_to_query(be, obj_name, pObject, vec);
+}
/* ================================================================= */
void
gnc_order_sql_initialize (void)
@@ -233,6 +235,5 @@ gnc_order_sql_initialize (void)
};
gnc_sql_register_backend(&be_data);
- gnc_sql_register_col_type_handler (CT_ORDERREF, &order_guid_handler);
}
/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-owner-sql.cpp b/src/backend/sql/gnc-owner-sql.cpp
index acdb4f0..0e354f9 100644
--- a/src/backend/sql/gnc-owner-sql.cpp
+++ b/src/backend/sql/gnc-owner-sql.cpp
@@ -41,17 +41,17 @@ extern "C"
#include "gncVendorP.h"
}
#include "gnc-backend-sql.h"
-#include "gnc-owner-sql.h"
static QofLogModule log_module = G_LOG_DOMAIN;
typedef void (*OwnerSetterFunc) (gpointer, GncOwner*);
typedef GncOwner* (*OwnerGetterFunc) (const gpointer);
-static void
-load_owner (const GncSqlBackend* be, GncSqlRow& row,
- QofSetterFunc setter, gpointer pObject,
- const GncSqlColumnTableEntry& table_row)
+template<> void
+GncSqlColumnTableEntryImpl<CT_OWNERREF>::load (const GncSqlBackend* be,
+ GncSqlRow& row,
+ QofIdTypeConst obj_name,
+ gpointer pObject) const noexcept
{
GncOwnerType type;
GncGUID guid;
@@ -62,14 +62,12 @@ load_owner (const GncSqlBackend* be, GncSqlRow& row,
g_return_if_fail (pObject != NULL);
auto book = be->book;
- auto buf = g_strdup_printf ("%s_type", table_row.col_name);
+ auto buf = std::string{m_col_name} + "_type";
try
{
- type = static_cast<decltype(type)>(row.get_int_at_col (buf));
- g_free (buf);
- buf = g_strdup_printf ("%s_guid", table_row.col_name);
- auto val = row.get_string_at_col (buf);
- g_free (buf);
+ type = static_cast<decltype(type)>(row.get_int_at_col (buf.c_str()));
+ buf = std::string{m_col_name} + "_guid";
+ auto val = row.get_string_at_col (buf.c_str());
string_to_guid (val.c_str(), &guid);
pGuid = &guid;
}
@@ -151,56 +149,44 @@ load_owner (const GncSqlBackend* be, GncSqlRow& row,
default:
PWARN ("Invalid owner type: %d\n", type);
}
- set_parameter (pObject, &owner, setter, table_row.gobj_param_name);
+ set_parameter (pObject, &owner, get_setter(obj_name), m_gobj_param_name);
}
-static void
-add_owner_col_info_to_list(const GncSqlBackend* be,
- const GncSqlColumnTableEntry& table_row,
- ColVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_OWNERREF>::add_to_table(const GncSqlBackend* be,
+ ColVec& vec) const noexcept
{
- gchar* buf;
-
g_return_if_fail (be != NULL);
- buf = g_strdup_printf ("%s_type", table_row.col_name);
+ auto buf = g_strdup_printf ("%s_type", m_col_name);
GncSqlColumnInfo info(buf, BCT_INT, 0, false, false,
- table_row.flags & COL_PKEY,
- table_row.flags & COL_NNUL);
+ m_flags & COL_PKEY, m_flags & COL_NNUL);
vec.emplace_back(std::move(info));
-
- buf = g_strdup_printf ("%s_guid", table_row.col_name);
- GncSqlColumnInfo info2(buf, BCT_STRING, GUID_ENCODING_LENGTH,
- false, false,
- table_row.flags & COL_PKEY,
- table_row.flags & COL_NNUL);
+/* Buf isn't leaking, it belongs to ColVec now. */
+ buf = g_strdup_printf ("%s_guid", m_col_name);
+ GncSqlColumnInfo info2(buf, BCT_STRING, GUID_ENCODING_LENGTH, false, false,
+ m_flags & COL_PKEY, m_flags & COL_NNUL);
vec.emplace_back(std::move(info2));
}
-static void
-add_value_owner_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
- const gpointer pObject,
- const GncSqlColumnTableEntry& table_row,
- PairVec& vec)
+template<> void
+GncSqlColumnTableEntryImpl<CT_OWNERREF>::add_to_query(const GncSqlBackend* be,
+ QofIdTypeConst obj_name,
+ const gpointer pObject,
+ PairVec& vec) const noexcept
{
g_return_if_fail (be != NULL);
g_return_if_fail (obj_name != NULL);
g_return_if_fail (pObject != NULL);
- auto getter = (OwnerGetterFunc)gnc_sql_get_getter (obj_name, table_row);
+ auto getter = (OwnerGetterFunc)get_getter (obj_name);
auto owner = (*getter) (pObject);
QofInstance* inst = nullptr;
GncOwnerType type;
- std::ostringstream buf;
-
- buf << table_row.col_name << "_type";
- std::string type_hdr{buf.str()};
- buf.str("");
- buf << table_row.col_name << "_guid";
- std::string guid_hdr{buf.str()};
- buf.str("");
+ auto type_hdr = std::string{m_col_name} + "_type";
+ auto guid_hdr = std::string{m_col_name} + "_guid";
if (owner != nullptr)
{
@@ -236,6 +222,8 @@ add_value_owner_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
return;
}
+ std::ostringstream buf;
+
buf << type;
vec.emplace_back(std::make_pair(type_hdr, buf.str()));
buf.str("");
@@ -246,17 +234,3 @@ add_value_owner_to_vec (const GncSqlBackend* be, QofIdTypeConst obj_name,
buf << "NULL";
vec.emplace_back(std::make_pair(guid_hdr, buf.str()));
}
-
-static GncSqlColumnTypeHandler owner_handler
-= { load_owner,
- add_owner_col_info_to_list,
- add_value_owner_to_vec
- };
-
-/* ================================================================= */
-void
-gnc_owner_sql_initialize (void)
-{
- gnc_sql_register_col_type_handler (CT_OWNERREF, &owner_handler);
-}
-/* ========================== END OF FILE ===================== */
diff --git a/src/backend/sql/gnc-owner-sql.h b/src/backend/sql/gnc-owner-sql.h
deleted file mode 100644
index 2c50115..0000000
--- a/src/backend/sql/gnc-owner-sql.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* gnc-owner-sql.h -- Owner SQL header
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, contact:
- *
- * Free Software Foundation Voice: +1-617-542-5942
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
- * Boston, MA 02110-1301, USA gnu at gnu.org
- */
-
-/** @file gnc-owner-sql.h
- * @brief load and save owner data to SQL
- * @author Copyright (c) 2007-2008 Phil Longstaff <plongstaff at rogers.com>
- *
- * This file implements the top-level QofBackend API for saving/
- * restoring data to/from an SQL database
- */
-
-#ifndef GNC_OWNER_SQL_H
-#define GNC_OWNER_SQL_H
-
-void gnc_owner_sql_initialize (void);
-
-#endif /* GNC_OWNER_SQL_H */
diff --git a/src/backend/sql/gnc-price-sql.cpp b/src/backend/sql/gnc-price-sql.cpp
index 39aa553..bea1c51 100644
--- a/src/backend/sql/gnc-price-sql.cpp
+++ b/src/backend/sql/gnc-price-sql.cpp
@@ -55,13 +55,16 @@ static QofLogModule log_module = G_LOG_DOMAIN;
static const EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "commodity_guid", CT_COMMODITYREF, 0, COL_NNUL, "commodity" },
- { "currency_guid", CT_COMMODITYREF, 0, COL_NNUL, "currency" },
- { "date", CT_TIMESPEC, 0, COL_NNUL, "date" },
- { "source", CT_STRING, PRICE_MAX_SOURCE_LEN, 0, "source" },
- { "type", CT_STRING, PRICE_MAX_TYPE_LEN, 0, "type" },
- { "value", CT_NUMERIC, 0, COL_NNUL, "value" }
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_COMMODITYREF>("commodity_guid", 0, COL_NNUL,
+ "commodity"),
+ gnc_sql_make_table_entry<CT_COMMODITYREF>("currency_guid", 0, COL_NNUL,
+ "currency"),
+ gnc_sql_make_table_entry<CT_TIMESPEC>("date", 0, COL_NNUL, "date"),
+ gnc_sql_make_table_entry<CT_STRING>("source", PRICE_MAX_SOURCE_LEN, 0,
+ "source"),
+ gnc_sql_make_table_entry<CT_STRING>("type", PRICE_MAX_TYPE_LEN, 0, "type"),
+ gnc_sql_make_table_entry<CT_NUMERIC>("value", 0, COL_NNUL, "value")
});
/* ================================================================= */
diff --git a/src/backend/sql/gnc-recurrence-sql.cpp b/src/backend/sql/gnc-recurrence-sql.cpp
index d1ecc76..c56f560 100644
--- a/src/backend/sql/gnc-recurrence-sql.cpp
+++ b/src/backend/sql/gnc-recurrence-sql.cpp
@@ -71,45 +71,42 @@ static void set_recurrence_period_start (gpointer pObject, gpointer pValue);
static const EntryVec col_table
({
- { "id", CT_INT, 0, COL_PKEY | COL_NNUL | COL_AUTOINC },
- {
- "obj_guid", CT_GUID, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_obj_guid, (QofSetterFunc)set_obj_guid
- },
- {
- "recurrence_mult", CT_INT, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_recurrence_mult, (QofSetterFunc)set_recurrence_mult
- },
- {
- "recurrence_period_type", CT_STRING, BUDGET_MAX_RECURRENCE_PERIOD_TYPE_LEN, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_recurrence_period_type, set_recurrence_period_type
- },
- {
- "recurrence_period_start", CT_GDATE, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_recurrence_period_start, set_recurrence_period_start
- },
- {
- "recurrence_weekend_adjust", CT_STRING, BUDGET_MAX_RECURRENCE_WEEKEND_ADJUST_LEN, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_recurrence_weekend_adjust, set_recurrence_weekend_adjust
- }
+ gnc_sql_make_table_entry<CT_INT>(
+ "id", 0, COL_PKEY | COL_NNUL | COL_AUTOINC),
+ gnc_sql_make_table_entry<CT_GUID>("obj_guid", 0, COL_NNUL,
+ (QofAccessFunc)get_obj_guid, (QofSetterFunc)set_obj_guid),
+ gnc_sql_make_table_entry<CT_INT>(
+ "recurrence_mult", 0, COL_NNUL,
+ (QofAccessFunc)get_recurrence_mult, (QofSetterFunc)set_recurrence_mult),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "recurrence_period_type", BUDGET_MAX_RECURRENCE_PERIOD_TYPE_LEN,
+ COL_NNUL,
+ (QofAccessFunc)get_recurrence_period_type, set_recurrence_period_type),
+ gnc_sql_make_table_entry<CT_GDATE>(
+ "recurrence_period_start", 0, COL_NNUL,
+ (QofAccessFunc)get_recurrence_period_start,
+ set_recurrence_period_start),
+ gnc_sql_make_table_entry<CT_STRING>(
+ "recurrence_weekend_adjust", BUDGET_MAX_RECURRENCE_WEEKEND_ADJUST_LEN,
+ COL_NNUL,
+ (QofAccessFunc)get_recurrence_weekend_adjust,
+ set_recurrence_weekend_adjust)
});
/* Special column table because we need to be able to access the table by
a column other than the primary key */
static const EntryVec guid_col_table
({
- {
- "obj_guid", CT_GUID, 0, 0, NULL, NULL,
- (QofAccessFunc)get_obj_guid, (QofSetterFunc)set_obj_guid
- }
+ gnc_sql_make_table_entry<CT_GUID>("obj_guid", 0, 0,
+ (QofAccessFunc)get_obj_guid,
+ (QofSetterFunc)set_obj_guid)
});
/* Special column table used to upgrade table from version 1 to 2 */
static const EntryVec weekend_adjust_col_table
({
- {
- "recurrence_weekend_adjust", CT_STRING, BUDGET_MAX_RECURRENCE_WEEKEND_ADJUST_LEN, 0,
- }
+ gnc_sql_make_table_entry<CT_STRING>(
+ "recurrence_weekend_adjust", BUDGET_MAX_RECURRENCE_WEEKEND_ADJUST_LEN, 0)
});
/* ================================================================= */
@@ -380,7 +377,7 @@ upgrade_recurrence_table_1_2 (GncSqlBackend* be)
gchar* weekend_adj_str = recurrenceWeekendAdjustToString (WEEKEND_ADJ_NONE);
gchar* update_query = g_strdup_printf ("UPDATE %s SET %s = '%s';",
TABLE_NAME,
- weekend_adjust_col_table[0].col_name,
+ weekend_adjust_col_table[0]->name(),
weekend_adj_str);
(void)gnc_sql_execute_nonselect_sql (be, update_query);
g_free (weekend_adj_str);
diff --git a/src/backend/sql/gnc-schedxaction-sql.cpp b/src/backend/sql/gnc-schedxaction-sql.cpp
index cbabe60..0f2fe6f 100644
--- a/src/backend/sql/gnc-schedxaction-sql.cpp
+++ b/src/backend/sql/gnc-schedxaction-sql.cpp
@@ -57,20 +57,28 @@ G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
static const EntryVec col_table
({
- { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
- { "name", CT_STRING, SX_MAX_NAME_LEN, 0, "name" },
- { "enabled", CT_BOOLEAN, 0, COL_NNUL, "enabled" },
- { "start_date", CT_GDATE, 0, 0, "start-date" },
- { "end_date", CT_GDATE, 0, 0, "end-date" },
- { "last_occur", CT_GDATE, 0, 0, "last-occurance-date" },
- { "num_occur", CT_INT, 0, COL_NNUL, "num-occurance" },
- { "rem_occur", CT_INT, 0, COL_NNUL, "rem-occurance" },
- { "auto_create", CT_BOOLEAN, 0, COL_NNUL, "auto-create" },
- { "auto_notify", CT_BOOLEAN, 0, COL_NNUL, "auto-create-notify" },
- { "adv_creation", CT_INT, 0, COL_NNUL, "advance-creation-days" },
- { "adv_notify", CT_INT, 0, COL_NNUL, "advance-reminder-days" },
- { "instance_count", CT_INT, 0, COL_NNUL, "instance-count" },
- { "template_act_guid", CT_ACCOUNTREF, 0, COL_NNUL, "template-account" },
+ gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
+ gnc_sql_make_table_entry<CT_STRING>("name", SX_MAX_NAME_LEN, 0, "name"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>("enabled", 0, COL_NNUL, "enabled"),
+ gnc_sql_make_table_entry<CT_GDATE>("start_date", 0, 0, "start-date"),
+ gnc_sql_make_table_entry<CT_GDATE>("end_date", 0, 0, "end-date"),
+ gnc_sql_make_table_entry<CT_GDATE>(
+ "last_occur", 0, 0, "last-occurance-date"),
+ gnc_sql_make_table_entry<CT_INT>(
+ "num_occur", 0, COL_NNUL, "num-occurance"),
+ gnc_sql_make_table_entry<CT_INT>("rem_occur", 0, COL_NNUL, "rem-occurance"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>(
+ "auto_create", 0, COL_NNUL, "auto-create"),
+ gnc_sql_make_table_entry<CT_BOOLEAN>(
+ "auto_notify", 0, COL_NNUL, "auto-create-notify"),
+ gnc_sql_make_table_entry<CT_INT>(
+ "adv_creation", 0, COL_NNUL, "advance-creation-days"),
+ gnc_sql_make_table_entry<CT_INT>(
+ "adv_notify", 0, COL_NNUL, "advance-reminder-days"),
+ gnc_sql_make_table_entry<CT_INT>(
+ "instance_count", 0, COL_NNUL, "instance-count"),
+ gnc_sql_make_table_entry<CT_ACCOUNTREF>(
+ "template_act_guid", 0, COL_NNUL, "template-account"),
});
/* ================================================================= */
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index 4d0bb69..e6b159e 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -113,59 +113,51 @@ enum
static const EntryVec col_table
{
/* col_name, col_type, size, flags, g0bj_param_name, qof_param_name, getter, setter */
- { "id", CT_INT, 0, COL_PKEY | COL_NNUL | COL_AUTOINC },
- {
- "obj_guid", CT_GUID, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_obj_guid, (QofSetterFunc)set_obj_guid
- },
- {
- "name", CT_STRING, SLOT_MAX_PATHNAME_LEN, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_path, set_path
- },
- {
- "slot_type", CT_INT, 0, COL_NNUL, NULL, NULL,
- (QofAccessFunc)get_slot_type, set_slot_type,
- },
- {
- "int64_val", CT_INT64, 0, 0, NULL, NULL,
- (QofAccessFunc)get_int64_val, (QofSetterFunc)set_int64_val
- },
- {
- "string_val", CT_STRING, SLOT_MAX_PATHNAME_LEN, 0, NULL, NULL,
- (QofAccessFunc)get_string_val, set_string_val
- },
- {
- "double_val", CT_DOUBLE, 0, 0, NULL, NULL,
- (QofAccessFunc)get_double_val, set_double_val
- },
- {
- "timespec_val", CT_TIMESPEC, 0, 0, NULL, NULL,
- (QofAccessFunc)get_timespec_val, (QofSetterFunc)set_timespec_val
- },
- {
- "guid_val", CT_GUID, 0, 0, NULL, NULL,
- (QofAccessFunc)get_guid_val, set_guid_val
- },
- {
- "numeric_val", CT_NUMERIC, 0, 0, NULL, NULL,
- (QofAccessFunc)get_numeric_val, (QofSetterFunc)set_numeric_val
- },
- {
- "gdate_val", CT_GDATE, 0, 0, NULL, NULL,
- (QofAccessFunc)get_gdate_val, (QofSetterFunc)set_gdate_val
- },
+ gnc_sql_make_table_entry<CT_INT>(
+ "id", 0, COL_PKEY | COL_NNUL | COL_AUTOINC),
+ gnc_sql_make_table_entry<CT_GUID>("obj_guid", 0, COL_NNUL,
+ (QofAccessFunc)get_obj_guid,
+ (QofSetterFunc)set_obj_guid),
+ gnc_sql_make_table_entry<CT_STRING>("name", SLOT_MAX_PATHNAME_LEN, COL_NNUL,
+ (QofAccessFunc)get_path, set_path),
+ gnc_sql_make_table_entry<CT_INT>("slot_type", 0, COL_NNUL,
+ (QofAccessFunc)get_slot_type,
+ set_slot_type),
+ gnc_sql_make_table_entry<CT_INT64>("int64_val", 0, 0,
+ (QofAccessFunc)get_int64_val,
+ (QofSetterFunc)set_int64_val),
+ gnc_sql_make_table_entry<CT_STRING>("string_val", SLOT_MAX_PATHNAME_LEN, 0,
+ (QofAccessFunc)get_string_val,
+ set_string_val),
+ gnc_sql_make_table_entry<CT_DOUBLE>("double_val", 0, 0,
+ (QofAccessFunc)get_double_val,
+ set_double_val),
+ gnc_sql_make_table_entry<CT_TIMESPEC>("timespec_val", 0, 0,
+ (QofAccessFunc)get_timespec_val,
+ (QofSetterFunc)set_timespec_val),
+ gnc_sql_make_table_entry<CT_GUID>("guid_val", 0, 0,
+ (QofAccessFunc)get_guid_val,
+ set_guid_val),
+ gnc_sql_make_table_entry<CT_NUMERIC>("numeric_val", 0, 0,
+ (QofAccessFunc)get_numeric_val,
+ (QofSetterFunc)set_numeric_val),
+ gnc_sql_make_table_entry<CT_GDATE>("gdate_val", 0, 0,
+ (QofAccessFunc)get_gdate_val,
+ (Qof