mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Make gnc_dbi_safe_sync_all safer.
Creates a new safe_sync function in struct provider and a new gnc_db_do_safe_sync_all function with the guts of gnc_dbi_do_safe_sync_all. The last calls the provider’s safe_sync function, which for SQLite3 and PGSql wraps the call to gnc_dbi_do_safe_sync_all in a SQL transaction. Unfortunately MySQL commits the transaction on the first schema-altering query (CREATE_TABLE in this case) without decrementing sql_savepoint, so raising an error when we try to release the (non-existent) save point at the end of writing the tables. Add a gnc_dbi_check_and_rollback_failed_save() to restore the database after a failed safe_save; this is performed at the next connection.
This commit is contained in:
parent
a70637f34d
commit
93301cd285
@ -63,6 +63,7 @@ typedef GSList* (*GET_TABLE_LIST_FN) ( dbi_conn conn, const gchar* dbname );
|
|||||||
typedef void (*APPEND_COLUMN_DEF_FN) ( GString* ddl, GncSqlColumnInfo* info );
|
typedef void (*APPEND_COLUMN_DEF_FN) ( GString* ddl, GncSqlColumnInfo* info );
|
||||||
typedef GSList* (*GET_INDEX_LIST_FN) ( dbi_conn conn );
|
typedef GSList* (*GET_INDEX_LIST_FN) ( dbi_conn conn );
|
||||||
typedef void (*DROP_INDEX_FN) ( dbi_conn conn, const gchar* index );
|
typedef void (*DROP_INDEX_FN) ( dbi_conn conn, const gchar* index );
|
||||||
|
typedef void (*SAFE_SYNC) ( QofBackend *qbe, QofBook * book );
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CREATE_TABLE_DDL_FN create_table_ddl;
|
CREATE_TABLE_DDL_FN create_table_ddl;
|
||||||
@ -70,6 +71,7 @@ typedef struct
|
|||||||
APPEND_COLUMN_DEF_FN append_col_def;
|
APPEND_COLUMN_DEF_FN append_col_def;
|
||||||
GET_INDEX_LIST_FN get_index_list;
|
GET_INDEX_LIST_FN get_index_list;
|
||||||
DROP_INDEX_FN drop_index;
|
DROP_INDEX_FN drop_index;
|
||||||
|
SAFE_SYNC safe_sync;
|
||||||
} provider_functions_t;
|
} provider_functions_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,13 +101,16 @@ static GSList* conn_get_table_list_sqlite3( dbi_conn conn, const gchar* dbname )
|
|||||||
static void append_sqlite3_col_def( GString* ddl, GncSqlColumnInfo* info );
|
static void append_sqlite3_col_def( GString* ddl, GncSqlColumnInfo* info );
|
||||||
static GSList *conn_get_index_list_sqlite3( dbi_conn conn );
|
static GSList *conn_get_index_list_sqlite3( dbi_conn conn );
|
||||||
static void conn_drop_index_sqlite3 (dbi_conn conn, const gchar *index );
|
static void conn_drop_index_sqlite3 (dbi_conn conn, const gchar *index );
|
||||||
|
static void conn_safe_sync_sqlite3 (QofBackend* qbe, QofBook *book);
|
||||||
|
|
||||||
static provider_functions_t provider_sqlite3 =
|
static provider_functions_t provider_sqlite3 =
|
||||||
{
|
{
|
||||||
conn_create_table_ddl_sqlite3,
|
conn_create_table_ddl_sqlite3,
|
||||||
conn_get_table_list_sqlite3,
|
conn_get_table_list_sqlite3,
|
||||||
append_sqlite3_col_def,
|
append_sqlite3_col_def,
|
||||||
conn_get_index_list_sqlite3,
|
conn_get_index_list_sqlite3,
|
||||||
conn_drop_index_sqlite3
|
conn_drop_index_sqlite3,
|
||||||
|
conn_safe_sync_sqlite3
|
||||||
};
|
};
|
||||||
#define SQLITE3_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
|
#define SQLITE3_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
|
||||||
|
|
||||||
@ -117,13 +120,16 @@ static /*@ null @*/ gchar* conn_create_table_ddl_mysql( GncSqlConnection* conn,
|
|||||||
static void append_mysql_col_def( GString* ddl, GncSqlColumnInfo* info );
|
static void append_mysql_col_def( GString* ddl, GncSqlColumnInfo* info );
|
||||||
static GSList *conn_get_index_list_mysql( dbi_conn conn );
|
static GSList *conn_get_index_list_mysql( dbi_conn conn );
|
||||||
static void conn_drop_index_mysql (dbi_conn conn, const gchar *index );
|
static void conn_drop_index_mysql (dbi_conn conn, const gchar *index );
|
||||||
|
static void conn_safe_sync_mysql (QofBackend* qbe, QofBook *book);
|
||||||
|
|
||||||
static provider_functions_t provider_mysql =
|
static provider_functions_t provider_mysql =
|
||||||
{
|
{
|
||||||
conn_create_table_ddl_mysql,
|
conn_create_table_ddl_mysql,
|
||||||
conn_get_table_list,
|
conn_get_table_list,
|
||||||
append_mysql_col_def,
|
append_mysql_col_def,
|
||||||
conn_get_index_list_mysql,
|
conn_get_index_list_mysql,
|
||||||
conn_drop_index_mysql
|
conn_drop_index_mysql,
|
||||||
|
conn_safe_sync_mysql
|
||||||
};
|
};
|
||||||
#define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
|
#define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
|
||||||
|
|
||||||
@ -134,6 +140,7 @@ static GSList* conn_get_table_list_pgsql( dbi_conn conn, const gchar* dbname );
|
|||||||
static void append_pgsql_col_def( GString* ddl, GncSqlColumnInfo* info );
|
static void append_pgsql_col_def( GString* ddl, GncSqlColumnInfo* info );
|
||||||
static GSList *conn_get_index_list_pgsql( dbi_conn conn );
|
static GSList *conn_get_index_list_pgsql( dbi_conn conn );
|
||||||
static void conn_drop_index_pgsql (dbi_conn conn, const gchar *index );
|
static void conn_drop_index_pgsql (dbi_conn conn, const gchar *index );
|
||||||
|
static void conn_safe_sync_pgsql (QofBackend* qbe, QofBook *book);
|
||||||
|
|
||||||
static provider_functions_t provider_pgsql =
|
static provider_functions_t provider_pgsql =
|
||||||
{
|
{
|
||||||
@ -141,14 +148,18 @@ static provider_functions_t provider_pgsql =
|
|||||||
conn_get_table_list_pgsql,
|
conn_get_table_list_pgsql,
|
||||||
append_pgsql_col_def,
|
append_pgsql_col_def,
|
||||||
conn_get_index_list_pgsql,
|
conn_get_index_list_pgsql,
|
||||||
conn_drop_index_pgsql
|
conn_drop_index_pgsql,
|
||||||
|
conn_safe_sync_pgsql
|
||||||
};
|
};
|
||||||
#define PGSQL_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 gboolean gnc_dbi_lock_database( QofBackend *qbe, gboolean ignore_lock );
|
||||||
static void gnc_dbi_unlock( QofBackend *qbe );
|
static void gnc_dbi_unlock( QofBackend *qbe );
|
||||||
|
static gboolean gnc_dbi_check_and_rollback_failed_save(QofBackend *qbe);
|
||||||
static gboolean save_may_clobber_data( QofBackend* qbe );
|
static gboolean save_may_clobber_data( QofBackend* qbe );
|
||||||
|
static gboolean gnc_dbi_do_safe_sync_all(QofBackend* qbe, QofBook *book);
|
||||||
|
static gboolean conn_table_operation(GncSqlConnection *sql_conn,
|
||||||
|
GSList *table_name_list, TableOpType op);
|
||||||
static /*@ null @*/ gchar* create_index_ddl( GncSqlConnection* conn,
|
static /*@ null @*/ gchar* create_index_ddl( GncSqlConnection* conn,
|
||||||
const gchar* index_name,
|
const gchar* index_name,
|
||||||
const gchar* table_name,
|
const gchar* table_name,
|
||||||
@ -308,6 +319,60 @@ gnc_dbi_transaction_rollback(QofBackend *qbe, dbi_conn conn)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gnc_dbi_do_safe_sync_all(QofBackend* qbe, QofBook* book)
|
||||||
|
{
|
||||||
|
GncDbiBackend *be = (GncDbiBackend*)qbe;
|
||||||
|
GncDbiSqlConnection *conn = (GncDbiSqlConnection*)(((GncSqlBackend*)be)->conn);
|
||||||
|
GSList *table_list, *index_list, *iter;
|
||||||
|
const gchar* dbname = NULL;
|
||||||
|
dbname = dbi_conn_get_option( be->conn, "dbname" );
|
||||||
|
table_list = conn->provider->get_table_list( conn->conn, dbname );
|
||||||
|
if ( !conn_table_operation( (GncSqlConnection*)conn, table_list,
|
||||||
|
backup ) )
|
||||||
|
{
|
||||||
|
qof_backend_set_error( qbe, ERR_BACKEND_SERVER_ERR );
|
||||||
|
conn_table_operation( (GncSqlConnection*)conn, table_list,
|
||||||
|
rollback );
|
||||||
|
LEAVE( "Failed to rename tables" );
|
||||||
|
gnc_table_slist_free( table_list );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
index_list = conn->provider->get_index_list( conn->conn );
|
||||||
|
for ( iter = index_list; iter != NULL; iter = g_slist_next( iter) )
|
||||||
|
{
|
||||||
|
const char *errmsg;
|
||||||
|
conn->provider->drop_index (conn->conn, iter->data);
|
||||||
|
if ( DBI_ERROR_NONE != dbi_conn_error( conn->conn, &errmsg ) )
|
||||||
|
{
|
||||||
|
qof_backend_set_error( qbe, ERR_BACKEND_SERVER_ERR );
|
||||||
|
gnc_table_slist_free( index_list );
|
||||||
|
conn_table_operation( (GncSqlConnection*)conn, table_list,
|
||||||
|
rollback );
|
||||||
|
gnc_table_slist_free( table_list );
|
||||||
|
LEAVE( "Failed to drop indexes %s", errmsg );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gnc_table_slist_free( index_list );
|
||||||
|
|
||||||
|
be->is_pristine_db = TRUE;
|
||||||
|
be->primary_book = book;
|
||||||
|
|
||||||
|
gnc_sql_sync_all( &be->sql_be, book );
|
||||||
|
if (qof_backend_check_error (qbe))
|
||||||
|
{
|
||||||
|
conn_table_operation( (GncSqlConnection*)conn, table_list,
|
||||||
|
rollback );
|
||||||
|
gnc_dbi_transaction_rollback(qbe, be->conn);
|
||||||
|
LEAVE( "Failed to create new database tables" );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
conn_table_operation( (GncSqlConnection*)conn, table_list,
|
||||||
|
drop_backup );
|
||||||
|
gnc_table_slist_free( table_list );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
/* ================================================================= */
|
/* ================================================================= */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -469,14 +534,17 @@ gnc_dbi_sqlite3_session_begin( QofBackend *qbe, QofSession *session,
|
|||||||
msg = "Locked";
|
msg = "Locked";
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( be->sql_be.conn != NULL )
|
if ( be->sql_be.conn != NULL )
|
||||||
{
|
{
|
||||||
gnc_sql_connection_dispose( be->sql_be.conn );
|
gnc_sql_connection_dispose( be->sql_be.conn );
|
||||||
}
|
}
|
||||||
be->sql_be.conn = create_dbi_connection( GNC_DBI_PROVIDER_SQLITE, qbe, be->conn );
|
be->sql_be.conn = create_dbi_connection( GNC_DBI_PROVIDER_SQLITE, qbe, be->conn );
|
||||||
be->sql_be.timespec_format = SQLITE3_TIMESPEC_STR_FORMAT;
|
be->sql_be.timespec_format = SQLITE3_TIMESPEC_STR_FORMAT;
|
||||||
|
if (! gnc_dbi_check_and_rollback_failed_save(qbe))
|
||||||
|
{
|
||||||
|
gnc_sql_connection_dispose(be->sql_be.conn);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
/* We should now have a proper session set up.
|
/* We should now have a proper session set up.
|
||||||
* Let's start logging */
|
* Let's start logging */
|
||||||
xaccLogSetBaseName (filepath);
|
xaccLogSetBaseName (filepath);
|
||||||
@ -519,6 +587,24 @@ conn_drop_index_sqlite3 (dbi_conn conn, const gchar *index )
|
|||||||
dbi_result_free( result );
|
dbi_result_free( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
conn_safe_sync_sqlite3 (QofBackend* qbe, QofBook *book)
|
||||||
|
{
|
||||||
|
GncDbiBackend *be = (GncDbiBackend*)qbe;
|
||||||
|
if (!gnc_dbi_transaction_begin(qbe, be->conn))
|
||||||
|
{
|
||||||
|
qof_backend_set_error( qbe, ERR_BACKEND_SERVER_ERR );
|
||||||
|
qof_backend_set_message(qbe, "Backend save failed, couldn't obtain the lock.");
|
||||||
|
}
|
||||||
|
if (!gnc_dbi_do_safe_sync_all(qbe, book))
|
||||||
|
gnc_dbi_transaction_rollback(qbe, be->conn);
|
||||||
|
else if (!gnc_dbi_transaction_commit(qbe, be->conn))
|
||||||
|
{
|
||||||
|
qof_backend_set_error(qbe, ERR_BACKEND_SERVER_ERR);
|
||||||
|
qof_backend_set_message(qbe, "Save failed, unable to commit the SQL transaction.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mysql_error_fn( dbi_conn conn, void* user_data )
|
mysql_error_fn( dbi_conn conn, void* user_data )
|
||||||
{
|
{
|
||||||
@ -1135,7 +1221,11 @@ gnc_dbi_mysql_session_begin( QofBackend* qbe, QofSession *session,
|
|||||||
}
|
}
|
||||||
be->sql_be.conn = create_dbi_connection( GNC_DBI_PROVIDER_MYSQL, qbe, be->conn );
|
be->sql_be.conn = create_dbi_connection( GNC_DBI_PROVIDER_MYSQL, qbe, be->conn );
|
||||||
be->sql_be.timespec_format = MYSQL_TIMESPEC_STR_FORMAT;
|
be->sql_be.timespec_format = MYSQL_TIMESPEC_STR_FORMAT;
|
||||||
|
if (! gnc_dbi_check_and_rollback_failed_save(qbe))
|
||||||
|
{
|
||||||
|
gnc_sql_connection_dispose(be->sql_be.conn);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
/* We should now have a proper session set up.
|
/* We should now have a proper session set up.
|
||||||
* Let's start logging */
|
* Let's start logging */
|
||||||
basename = g_strjoin("_", protocol, host, username, dbname, NULL);
|
basename = g_strjoin("_", protocol, host, username, dbname, NULL);
|
||||||
@ -1218,6 +1308,18 @@ conn_drop_index_mysql (dbi_conn conn, const gchar *index )
|
|||||||
g_strfreev (index_table_split);
|
g_strfreev (index_table_split);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* MySQL automatically commits after any operation that changes a
|
||||||
|
* database's structure, like CREATE_TABLE or DROP_TABLE. Even if one
|
||||||
|
* disables that the changes can't be rolled back, so there's
|
||||||
|
* no way to make the save atomic. If the save doesn't complete we
|
||||||
|
* must rely on gnc_dbi_check_and_rollback_failed_save.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
conn_safe_sync_mysql (QofBackend* qbe, QofBook *book)
|
||||||
|
{
|
||||||
|
gnc_dbi_do_safe_sync_all(qbe, book);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pgsql_error_fn( dbi_conn conn, void* user_data )
|
pgsql_error_fn( dbi_conn conn, void* user_data )
|
||||||
{
|
{
|
||||||
@ -1486,7 +1588,11 @@ gnc_dbi_postgres_session_begin( QofBackend *qbe, QofSession *session,
|
|||||||
}
|
}
|
||||||
be->sql_be.conn = create_dbi_connection( GNC_DBI_PROVIDER_PGSQL, qbe, be->conn );
|
be->sql_be.conn = create_dbi_connection( GNC_DBI_PROVIDER_PGSQL, qbe, be->conn );
|
||||||
be->sql_be.timespec_format = PGSQL_TIMESPEC_STR_FORMAT;
|
be->sql_be.timespec_format = PGSQL_TIMESPEC_STR_FORMAT;
|
||||||
|
if (! gnc_dbi_check_and_rollback_failed_save(qbe))
|
||||||
|
{
|
||||||
|
gnc_sql_connection_dispose(be->sql_be.conn);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
/* We should now have a proper session set up.
|
/* We should now have a proper session set up.
|
||||||
* Let's start logging */
|
* Let's start logging */
|
||||||
basename = g_strjoin("_", protocol, host, username, dbname, NULL);
|
basename = g_strjoin("_", protocol, host, username, dbname, NULL);
|
||||||
@ -1539,6 +1645,23 @@ conn_drop_index_pgsql (dbi_conn conn, const gchar *index )
|
|||||||
dbi_result_free( result );
|
dbi_result_free( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
conn_safe_sync_pgsql (QofBackend* qbe, QofBook *book)
|
||||||
|
{
|
||||||
|
GncDbiBackend *be = (GncDbiBackend*)qbe;
|
||||||
|
if (!gnc_dbi_transaction_begin(qbe, be->conn))
|
||||||
|
{
|
||||||
|
qof_backend_set_error( qbe, ERR_BACKEND_SERVER_ERR );
|
||||||
|
qof_backend_set_message(qbe, "Backend save failed, couldn't obtain the lock.");
|
||||||
|
}
|
||||||
|
if (!gnc_dbi_do_safe_sync_all(qbe, book))
|
||||||
|
gnc_dbi_transaction_rollback(qbe, be->conn);
|
||||||
|
else if (!gnc_dbi_transaction_commit(qbe, be->conn))
|
||||||
|
{
|
||||||
|
qof_backend_set_error(qbe, ERR_BACKEND_SERVER_ERR);
|
||||||
|
qof_backend_set_message(qbe, "Save failed, unable to commit the SQL transaction.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================================= */
|
/* ================================================================= */
|
||||||
|
|
||||||
@ -1791,59 +1914,63 @@ gnc_dbi_safe_sync_all( QofBackend *qbe, QofBook *book )
|
|||||||
{
|
{
|
||||||
GncDbiBackend *be = (GncDbiBackend*)qbe;
|
GncDbiBackend *be = (GncDbiBackend*)qbe;
|
||||||
GncDbiSqlConnection *conn = (GncDbiSqlConnection*)(((GncSqlBackend*)be)->conn);
|
GncDbiSqlConnection *conn = (GncDbiSqlConnection*)(((GncSqlBackend*)be)->conn);
|
||||||
GSList *table_list, *index_list, *iter;
|
|
||||||
const gchar* dbname = NULL;
|
|
||||||
|
|
||||||
g_return_if_fail( be != NULL );
|
g_return_if_fail( be != NULL );
|
||||||
g_return_if_fail( book != NULL );
|
g_return_if_fail( book != NULL );
|
||||||
|
conn->provider->safe_sync(qbe, book);
|
||||||
ENTER( "book=%p, primary=%p", book, be->primary_book );
|
ENTER( "book=%p, primary=%p", book, be->primary_book );
|
||||||
dbname = dbi_conn_get_option( be->conn, "dbname" );
|
|
||||||
table_list = conn->provider->get_table_list( conn->conn, dbname );
|
|
||||||
if ( !conn_table_operation( (GncSqlConnection*)conn, table_list,
|
|
||||||
backup ) )
|
|
||||||
{
|
|
||||||
qof_backend_set_error( qbe, ERR_BACKEND_SERVER_ERR );
|
|
||||||
conn_table_operation( (GncSqlConnection*)conn, table_list,
|
|
||||||
rollback );
|
|
||||||
LEAVE( "Failed to rename tables" );
|
|
||||||
gnc_table_slist_free( table_list );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
index_list = conn->provider->get_index_list( conn->conn );
|
|
||||||
for ( iter = index_list; iter != NULL; iter = g_slist_next( iter) )
|
|
||||||
{
|
|
||||||
const char *errmsg;
|
|
||||||
conn->provider->drop_index (conn->conn, iter->data);
|
|
||||||
if ( DBI_ERROR_NONE != dbi_conn_error( conn->conn, &errmsg ) )
|
|
||||||
{
|
|
||||||
qof_backend_set_error( qbe, ERR_BACKEND_SERVER_ERR );
|
|
||||||
gnc_table_slist_free( index_list );
|
|
||||||
conn_table_operation( (GncSqlConnection*)conn, table_list,
|
|
||||||
rollback );
|
|
||||||
gnc_table_slist_free( table_list );
|
|
||||||
LEAVE( "Failed to drop indexes %s", errmsg );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gnc_table_slist_free( index_list );
|
|
||||||
|
|
||||||
be->is_pristine_db = TRUE;
|
|
||||||
be->primary_book = book;
|
|
||||||
|
|
||||||
gnc_sql_sync_all( &be->sql_be, book );
|
|
||||||
if (qof_backend_check_error (qbe))
|
|
||||||
{
|
|
||||||
conn_table_operation( (GncSqlConnection*)conn, table_list,
|
|
||||||
rollback );
|
|
||||||
LEAVE( "Failed to create new database tables" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
conn_table_operation( (GncSqlConnection*)conn, table_list,
|
|
||||||
drop_backup );
|
|
||||||
gnc_table_slist_free( table_list );
|
|
||||||
LEAVE("book=%p", book);
|
LEAVE("book=%p", book);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
find_backup_cb(gconstpointer data, gconstpointer user)
|
||||||
|
{
|
||||||
|
char* table_name = (char*)data;
|
||||||
|
char* suffix = (char*)user;
|
||||||
|
if (g_str_has_suffix(table_name, suffix))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gnc_dbi_check_and_rollback_failed_save(QofBackend *qbe)
|
||||||
|
{
|
||||||
|
GncDbiBackend *be = (GncDbiBackend*)qbe;
|
||||||
|
GncSqlConnection *conn = (GncSqlConnection*)(((GncSqlBackend*)be)->conn);
|
||||||
|
dbi_result result;
|
||||||
|
GSList *table_list = NULL;
|
||||||
|
const gchar* dbname = NULL;
|
||||||
|
static const char* suffix = "%back";
|
||||||
|
g_return_val_if_fail(be != NULL, FALSE);
|
||||||
|
g_return_val_if_fail(conn != NULL, FALSE);
|
||||||
|
|
||||||
|
dbname = dbi_conn_get_option(be->conn, "dbname");
|
||||||
|
result = dbi_conn_get_table_list(be->conn, dbname, suffix);
|
||||||
|
while (dbi_result_next_row(result) != 0)
|
||||||
|
{
|
||||||
|
const char *table_name = dbi_result_get_string_idx(result, 1);
|
||||||
|
table_list = g_slist_prepend(table_list, g_strdup(table_name));
|
||||||
|
}
|
||||||
|
if (result)
|
||||||
|
dbi_result_free(result);
|
||||||
|
if (table_list == NULL)
|
||||||
|
return TRUE;
|
||||||
|
if (!gnc_dbi_transaction_begin(qbe, be->conn))
|
||||||
|
{
|
||||||
|
qof_backend_set_message(qbe, "Backup tables found from a failed safe sync, unable to lock the database to restore them.");
|
||||||
|
g_slist_free_full(table_list, g_free);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
conn_table_operation((GncSqlConnection*)conn, table_list, rollback);
|
||||||
|
g_slist_free_full(table_list, g_free);
|
||||||
|
if (!gnc_dbi_transaction_commit(qbe, be->conn))
|
||||||
|
{
|
||||||
|
qof_backend_set_message(qbe, "Backup tables found from a failed safe sync, unable to commit the restoration transaction.");
|
||||||
|
gnc_dbi_transaction_rollback(qbe, be->conn);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================================= */
|
/* ================================================================= */
|
||||||
static void
|
static void
|
||||||
gnc_dbi_begin_edit( QofBackend *qbe, QofInstance *inst )
|
gnc_dbi_begin_edit( QofBackend *qbe, QofInstance *inst )
|
||||||
|
Loading…
Reference in New Issue
Block a user