Index: src/backend/dbi/gnc-backend-dbi.c
===================================================================
--- src/backend/dbi/gnc-backend-dbi.c	(revision 18683)
+++ src/backend/dbi/gnc-backend-dbi.c	(working copy)
@@ -149,11 +149,50 @@
     dbi_conn conn;
     /*@ observer @*/
     provider_functions_t* provider;
+    gint last_error;        // Code of the last error that occurred. This is set in the error callback function
+    gint error_repeat;      // Used in case of transient errors. After such error, another attempt at the
+                            // original call is allowed. error_repeat tracks the number of attempts and can
+                            // be used to prevent infinite loops.
+    gboolean retry;         // Signals the calling function that it should retry (the error handler detected
+                            // transient error and managed to resolve it, but it can't run the original query)
 } GncDbiSqlConnection;
 
+typedef enum
+{
+    DBI_NO_ERROR = 0,
+    DBI_ERR_CONN_TIMEOUT,
+    DBI_ERR_CONN_FAILED,
+    DBI_ERR_DB_NOT_EXIST,
+    DBI_ERR_UNKNOWN
+} GncDbiErrorType;
+
+#define DBI_MAX_CONN_ATTEMPTS 5
+
 /* ================================================================= */
 
 static void
+gnc_dbi_set_error( GncDbiSqlConnection* dbi_conn, gint last_error,
+                   gint error_repeat, gboolean retry )
+{
+    g_return_if_fail( dbi_conn != NULL );
+
+    dbi_conn->last_error = last_error;
+    if ( error_repeat > 0 )
+        dbi_conn->error_repeat = dbi_conn->error_repeat + error_repeat;
+    else
+        dbi_conn->error_repeat = 0;
+    dbi_conn->retry = retry;
+}
+
+static void
+gnc_dbi_init_error( GncDbiSqlConnection* dbi_conn )
+{
+    gnc_dbi_set_error( dbi_conn, 0, 0, FALSE );
+}
+
+/* ================================================================= */
+
+static void
 create_tables_cb( const gchar* type, gpointer data_p, gpointer be_p )
 {
     GncSqlObjectBackend* pData = data_p;
@@ -171,11 +210,13 @@
 static void
 sqlite3_error_fn( dbi_conn conn, /*@ unused @*/ void* user_data )
 {
-    //GncDbiBackend *be = (GncDbiBackend*)user_data;
+    GncDbiBackend *be = (GncDbiBackend*)user_data;
+    GncDbiSqlConnection *dbi_conn = (GncDbiSqlConnection*)be->sql_be.conn;
     const gchar* msg;
 
     (void)dbi_conn_error( conn, &msg );
     PERR( "DBI error: %s\n", msg );
+    gnc_dbi_set_error( dbi_conn, DBI_ERR_UNKNOWN, 0, FALSE );
 }
 
 static void
@@ -278,17 +319,35 @@
 mysql_error_fn( dbi_conn conn, void* user_data )
 {
     GncDbiBackend *be = (GncDbiBackend*)user_data;
+    GncDbiSqlConnection *dbi_conn = (GncDbiSqlConnection*)be->sql_be.conn;
     const gchar* msg;
+    gint err_num;
 
-    (void)dbi_conn_error( conn, &msg );
-    if ( g_str_has_prefix( msg, "1049: Unknown database" ) )
+    err_num = dbi_conn_error( conn, &msg );
+    if ( err_num == 1049 )          // Database doesn't exist
     {
         PINFO( "DBI error: %s\n", msg );
         be->exists = FALSE;
+        gnc_dbi_set_error( dbi_conn, DBI_ERR_DB_NOT_EXIST, 0, FALSE );
     }
-    else
+    else if ( err_num == 2006 )     // Server has gone away
     {
+        if (dbi_conn->error_repeat > DBI_MAX_CONN_ATTEMPTS )
+        {
+            PERR( "DBI error: %s - Failed to reconnect after %d attempts.\n", msg, DBI_MAX_CONN_ATTEMPTS );
+            gnc_dbi_set_error( dbi_conn, DBI_ERR_CONN_FAILED, 0, FALSE );
+        } else
+        {
+            PINFO( "DBI error: %s - Reconnecting...\n", msg );
+            gnc_dbi_set_error( dbi_conn, DBI_ERR_DB_NOT_EXIST, 1, TRUE );
+
+            (void)dbi_conn_connect( conn );
+        }
+    }
+    else                            // Any other error
+    {
         PERR( "DBI error: %s\n", msg );
+        gnc_dbi_set_error( dbi_conn, DBI_ERR_UNKNOWN, 0, FALSE );
     }
 }
 
@@ -511,6 +570,7 @@
 pgsql_error_fn( dbi_conn conn, void* user_data )
 {
     GncDbiBackend *be = (GncDbiBackend*)user_data;
+    GncDbiSqlConnection *dbi_conn = (GncDbiSqlConnection*)be->sql_be.conn;
     const gchar* msg;
 
     (void)dbi_conn_error( conn, &msg );
@@ -519,10 +579,12 @@
     {
         PINFO( "DBI error: %s\n", msg );
         be->exists = FALSE;
+        gnc_dbi_set_error( dbi_conn, DBI_ERR_DB_NOT_EXIST, 0, FALSE );
     }
     else
     {
         PERR( "DBI error: %s\n", msg );
+        gnc_dbi_set_error( dbi_conn, DBI_ERR_UNKNOWN, 0, FALSE );
     }
 }
 
@@ -802,7 +864,10 @@
             const gchar* table_name = (const gchar*)node->data;
             dbi_result result;
 
-            result = dbi_conn_queryf( be->conn, "DROP TABLE %s", table_name );
+            do {
+                gnc_dbi_init_error( ((GncDbiSqlConnection*)(be->sql_be.conn)) );
+                result = dbi_conn_queryf( be->conn, "DROP TABLE %s", table_name );
+            } while ( ((GncDbiSqlConnection*)(be->sql_be.conn))->retry );
             if ( result != NULL )
             {
                 status = dbi_result_free( result );
@@ -1416,7 +1481,10 @@
     dbi_result result;
 
     DEBUG( "SQL: %s\n", dbi_stmt->sql->str );
-    result = dbi_conn_query( dbi_conn->conn, dbi_stmt->sql->str );
+    do {
+        gnc_dbi_init_error( dbi_conn );
+        result = dbi_conn_query( dbi_conn->conn, dbi_stmt->sql->str );
+    } while ( dbi_conn->retry );
     if ( result == NULL )
     {
         PERR( "Error executing SQL %s\n", dbi_stmt->sql->str );
@@ -1435,7 +1503,10 @@
     gint status;
 
     DEBUG( "SQL: %s\n", dbi_stmt->sql->str );
-    result = dbi_conn_query( dbi_conn->conn, dbi_stmt->sql->str );
+    do {
+        gnc_dbi_init_error( dbi_conn );
+        result = dbi_conn_query( dbi_conn->conn, dbi_stmt->sql->str );
+    } while( dbi_conn->retry );
     if ( result == NULL )
     {
         PERR( "Error executing SQL %s\n", dbi_stmt->sql->str );
@@ -1513,15 +1584,11 @@
     gint status;
 
     DEBUG( "BEGIN\n" );
-    result = dbi_conn_queryf( dbi_conn->conn, "BEGIN" );
 
-    /* Handle MySQL connection timeouts with reconnect */
-    if (result == NULL && dbi_conn_error( dbi_conn->conn, NULL ) == 2006 )
-    {
-        DEBUG( "MySQL server has gone away, reconnecting and retrying...\n" );
-        (void)dbi_conn_connect( dbi_conn->conn );
+    do {
+        gnc_dbi_init_error( dbi_conn );
         result = dbi_conn_queryf( dbi_conn->conn, "BEGIN" );
-    }
+    } while( dbi_conn->retry );
 
     status = dbi_result_free( result );
     if ( status < 0 )
@@ -2016,6 +2083,9 @@
     dbi_conn->qbe = qbe;
     dbi_conn->conn = conn;
     dbi_conn->provider = provider;
+    dbi_conn->last_error = 0;
+    dbi_conn->error_repeat = 0;
+    dbi_conn->retry = FALSE;
 
     return (GncSqlConnection*)dbi_conn;
 }
