tdf#117118 - Saves data automatically in Firebird embedded database

Saves data when dispossing connection regardless of
whether or not the save button is pressed

Change-Id: I501fbc3d89ff52695f42196b2627e26c2011f75b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148368
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/connectivity/source/drivers/firebird/Connection.cxx b/connectivity/source/drivers/firebird/Connection.cxx
index 5b8cdb7..4e2bce4 100644
--- a/connectivity/source/drivers/firebird/Connection.cxx
+++ b/connectivity/source/drivers/firebird/Connection.cxx
@@ -339,11 +339,6 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >&
    }
}

void Connection::notifyDatabaseModified()
{
    if (m_xParentDocument.is()) // Only true in embedded mode
        m_xParentDocument->setModified(true);
}

//----- XServiceInfo ---------------------------------------------------------
IMPLEMENT_SERVICE_INFO(Connection, "com.sun.star.sdbc.drivers.firebird.Connection",
@@ -822,41 +817,7 @@ void SAL_CALL Connection::documentEventOccured( const DocumentEvent& Event )
    if ( !(m_bIsEmbedded && m_xEmbeddedStorage.is()) )
        return;

    SAL_INFO("connectivity.firebird", "Writing .fbk from running db");
    try
    {
        runBackupService(isc_action_svc_backup);
    }
    catch (const SQLException& e)
    {
        auto a = cppu::getCaughtException();
        throw WrappedTargetRuntimeException(e.Message, e.Context, a);
    }


    Reference< XStream > xDBStream(m_xEmbeddedStorage->openStreamElement(our_sFBKLocation,
                                                    ElementModes::WRITE));

    // TODO: verify the backup actually exists -- the backup service
    // can fail without giving any sane error messages / telling us
    // that it failed.
    using namespace ::comphelper;
    Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
    Reference< XInputStream > xInputStream;
    if (!xContext.is())
        return;

    xInputStream =
            OStorageHelper::GetInputStreamFromURL(m_sFBKPath, xContext);
    if (xInputStream.is())
        OStorageHelper::CopyInputToOutput( xInputStream,
                                    xDBStream->getOutputStream());

    // remove old fdb file if exists
    uno::Reference< ucb::XSimpleFileAccess > xFileAccess =
        ucb::SimpleFileAccess::create(xContext);
    if (xFileAccess->exists(m_sFirebirdURL))
        xFileAccess->kill(m_sFirebirdURL);
    storeDatabase();
}
// XEventListener
void SAL_CALL Connection::disposing(const EventObject& /*rSource*/)
@@ -938,13 +899,59 @@ void Connection::disposing()
            evaluateStatusVector(status, u"isc_detach_database", *this);
        }
    }
    // TODO: write to storage again?

    storeDatabase();

    cppu::WeakComponentImplHelperBase::disposing();

    m_pDatabaseFileDir.reset();
}

void Connection::storeDatabase()
{
    MutexGuard aGuard(m_aMutex);

    if (m_bIsEmbedded && m_xEmbeddedStorage.is())
    {
        SAL_INFO("connectivity.firebird", "Writing .fbk from running db");
        try
        {
            runBackupService(isc_action_svc_backup);
        }
        catch (const SQLException& e)
        {
            auto a = cppu::getCaughtException();
            throw WrappedTargetRuntimeException(e.Message, e.Context, a);
        }

        Reference<XStream> xDBStream(
            m_xEmbeddedStorage->openStreamElement(our_sFBKLocation, ElementModes::WRITE));

        using namespace ::comphelper;
        Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
        Reference<XInputStream> xInputStream;
        if (!xContext.is())
            return;

        xInputStream = OStorageHelper::GetInputStreamFromURL(m_sFBKPath, xContext);
        if (xInputStream.is())
            OStorageHelper::CopyInputToOutput(xInputStream, xDBStream->getOutputStream());

        // remove old fdb and fbk files if exist
        uno::Reference<ucb::XSimpleFileAccess> xFileAccess
            = ucb::SimpleFileAccess::create(xContext);
        if (xFileAccess->exists(m_sFirebirdURL))
            xFileAccess->kill(m_sFirebirdURL);

        if (xFileAccess->exists(m_sFBKPath))
            xFileAccess->kill(m_sFBKPath);

        cppu::WeakComponentImplHelperBase::disposing();

        m_pDatabaseFileDir.reset();
    }
}

void Connection::disposeStatements()
{
    MutexGuard aGuard(m_aMutex);
diff --git a/connectivity/source/drivers/firebird/Connection.hxx b/connectivity/source/drivers/firebird/Connection.hxx
index fa89643..404f258 100644
--- a/connectivity/source/drivers/firebird/Connection.hxx
+++ b/connectivity/source/drivers/firebird/Connection.hxx
@@ -171,15 +171,6 @@ namespace connectivity::firebird
            /// @throws css::sdbc::SQLException
            isc_tr_handle&  getTransaction();

            /**
              * Must be called anytime the underlying database is likely to have
              * changed.
              *
              * This is used to notify the database document of any changes, so
              * that the user is informed of any pending changes needing to be
              * saved.
              */
            void notifyDatabaseModified();

            /**
             * Create a new Blob tied to this connection. Blobs are tied to a
@@ -203,6 +194,11 @@ namespace connectivity::firebird
            css::uno::Reference< css::sdbcx::XTablesSupplier >
                createCatalog();

            /**
            * Backup and store embedded extracted database to the .odb file
            */
            void storeDatabase();

            // OComponentHelper
            virtual void SAL_CALL disposing() override;

diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx
index 608d05c..35847d0 100644
--- a/connectivity/source/drivers/firebird/PreparedStatement.cxx
+++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx
@@ -334,9 +334,6 @@ sal_Bool SAL_CALL OPreparedStatement::execute()
                                  m_aStatementHandle,
                                  m_pOutSqlda);

    if (getStatementChangeCount() > 0)
        m_pConnection->notifyDatabaseModified();

    return m_xResultSet.is();
    // TODO: implement handling of multiple ResultSets.
}
diff --git a/connectivity/source/drivers/firebird/Statement.cxx b/connectivity/source/drivers/firebird/Statement.cxx
index fec8341..5d9abdf 100644
--- a/connectivity/source/drivers/firebird/Statement.cxx
+++ b/connectivity/source/drivers/firebird/Statement.cxx
@@ -125,11 +125,6 @@ uno::Reference< XResultSet > SAL_CALL OStatement::executeQuery(const OUString& s
    if (isDDLStatement())
    {
        m_pConnection->commit();
        m_pConnection->notifyDatabaseModified();
    }
    else if (getStatementChangeCount() > 0)
    {
        m_pConnection->notifyDatabaseModified();
    }

    return m_xResultSet;