mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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.
This commit is contained in:
parent
d106346316
commit
6f67e2dd1a
@ -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;
|
||||
@ -121,8 +112,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 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->connect(nullptr);
|
||||
be->connect(
|
||||
new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
|
||||
qbe, conn, lock_table));
|
||||
}
|
||||
be->sql_be.conn = new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_MYSQL>,
|
||||
qbe, be->conn);
|
||||
}
|
||||
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->connect(nullptr);
|
||||
be->connect(
|
||||
new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_PGSQL>,
|
||||
qbe, conn, lock_table));
|
||||
}
|
||||
be->sql_be.conn = new GncDbiSqlConnection (new GncDbiProviderImpl<DbType::DBI_PGSQL>,
|
||||
qbe, be->conn);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
29
src/backend/dbi/gnc-dbisqlconnection.hpp
Normal file
29
src/backend/dbi/gnc-dbisqlconnection.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
/********************************************************************
|
||||
* gnc-dbisqlconnection.hpp: Encapsulate libdbi dbi_conn *
|
||||
* *
|
||||
* Copyright 2016 John Ralls <jralls@ceridwen.us> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
||||
\********************************************************************/
|
||||
#ifndef _GNC_DBISQLCONNECTION_HPP_
|
||||
#define _GNC_DBISQLCONNECTION_HPP_
|
||||
/**
|
||||
* Encapsulate a libdbi dbi_conn connection.
|
||||
*/
|
||||
|
||||
#endif //_GNC_DBISQLCONNECTION_HPP_
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
if (be->be.percentage != NULL)
|
||||
(be->be.percentage) (NULL, 101.0);
|
||||
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 (conn != nullptr)
|
||||
connect (conn);
|
||||
}
|
||||
|
||||
static void
|
||||
finish_progress (GncSqlBackend* be)
|
||||
void
|
||||
GncSqlBackend::connect(GncSqlConnection *conn) noexcept
|
||||
{
|
||||
if (be->be.percentage != NULL)
|
||||
(be->be.percentage) (NULL, -1.0);
|
||||
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 (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)
|
||||
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());
|
||||
int version = be->get_table_version (m_table_name);
|
||||
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);
|
||||
{
|
||||
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)
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user