/* MySQL commits the transaction and all savepoints after the first CREATE * TABLE, crashing when we try to RELEASE SAVEPOINT because the savepoint * doesn't exist after the commit. We must run without a wrapping transaction in * that case. */ template <> void GncDbiBackend<DbType::DBI_MYSQL>::safe_sync (QofBook* book) { auto conn = dynamic_cast<GncDbiSqlConnection*>(m_conn); g_return_if_fail (conn != nullptr); g_return_if_fail (book != nullptr); ENTER ("book=%p, primary=%p", book, m_book); if (!conn->table_operation (TableOpType::backup)) { set_error(ERR_BACKEND_SERVER_ERR); conn->table_operation (TableOpType::rollback); LEAVE ("Failed to rename tables"); return; } if (!conn->drop_indexes()) { conn->table_operation (TableOpType::rollback); set_error (ERR_BACKEND_SERVER_ERR); set_message("Failed to drop indexes"); LEAVE ("Failed to drop indexes"); return; } sync(m_book); if (check_error()) { conn->table_operation (TableOpType::rollback); LEAVE ("Failed to create new database tables"); return; } conn->table_operation (TableOpType::drop_backup); LEAVE ("book=%p", m_book); }
/** * Safely resave a database by renaming all of its tables, recreating * everything, and then dropping the backup tables only if there were * no errors. If there are errors, drop the new tables and restore the * originals. * * @param qbe: QofBackend for the session. * @param book: QofBook to be saved in the database. */ void gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book) { GncDbiBackend* be = (GncDbiBackend*)qbe; 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->m_book); auto table_list = conn->m_provider->get_table_list (conn->conn(), ""); if (!conn->table_operation (table_list, backup)) { qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); conn->table_operation (table_list, rollback); LEAVE ("Failed to rename tables"); return; } auto index_list = conn->m_provider->get_index_list (conn->m_conn); for (auto index : index_list) { const char* errmsg; conn->m_provider->drop_index (conn->m_conn, index); if (DBI_ERROR_NONE != dbi_conn_error (conn->m_conn, &errmsg)) { qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); conn->table_operation (table_list, rollback); LEAVE ("Failed to drop indexes %s", errmsg); return; } } gnc_sql_sync_all (be, book); if (qof_backend_check_error (qbe)) { conn->table_operation (table_list, rollback); LEAVE ("Failed to create new database tables"); return; } conn->table_operation (table_list, drop_backup); LEAVE ("book=%p", book); }
/** * Safely resave a database by renaming all of its tables, recreating * everything, and then dropping the backup tables only if there were * no errors. If there are errors, drop the new tables and restore the * originals. * * @param book: QofBook to be saved in the database. */ template <DbType Type> void GncDbiBackend<Type>::safe_sync (QofBook* book) { auto conn = dynamic_cast<GncDbiSqlConnection*>(m_conn); g_return_if_fail (conn != nullptr); g_return_if_fail (book != nullptr); ENTER ("book=%p, primary=%p", book, m_book); if (!conn->begin_transaction()) { LEAVE("Failed to obtain a transaction."); return; } if (!conn->table_operation (TableOpType::backup)) { conn->rollback_transaction(); LEAVE ("Failed to rename tables"); return; } if (!conn->drop_indexes()) { conn->rollback_transaction(); LEAVE ("Failed to drop indexes"); return; } sync(m_book); if (check_error()) { conn->rollback_transaction(); LEAVE ("Failed to create new database tables"); return; } conn->table_operation (TableOpType::drop_backup); conn->commit_transaction(); LEAVE ("book=%p", m_book); }