From e6238c18b0a0e16b6ff420798f4561f9a9b9b0ba Mon Sep 17 00:00:00 2001
From: Even Rouault <even.rouault@spatialys.com>
Date: Wed, 15 Jan 2025 19:10:07 +0100
Subject: [PATCH] Remove ogremulatedtransaction.h/cpp which was only used by
 the write side of the FileGDB driver

---
 ogr/ogrsf_frmts/generic/CMakeLists.txt        |   1 -
 .../generic/ogremulatedtransaction.cpp        | 768 ------------------
 .../generic/ogremulatedtransaction.h          | 115 ---
 3 files changed, 884 deletions(-)
 delete mode 100644 ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
 delete mode 100644 ogr/ogrsf_frmts/generic/ogremulatedtransaction.h

diff --git a/ogr/ogrsf_frmts/generic/CMakeLists.txt b/ogr/ogrsf_frmts/generic/CMakeLists.txt
index d91cca719e6b..a3ebb6142954 100644
--- a/ogr/ogrsf_frmts/generic/CMakeLists.txt
+++ b/ogr/ogrsf_frmts/generic/CMakeLists.txt
@@ -38,7 +38,6 @@ add_library(
   ogrlayerpool.cpp
   ogrlayerdecorator.cpp
   ogreditablelayer.cpp
-  ogremulatedtransaction.cpp
   ogrmutexeddatasource.cpp
   ogrmutexedlayer.cpp
   ograrrowarrayhelper.cpp)
diff --git a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
deleted file mode 100644
index 5ae5dea2b746..000000000000
--- a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
+++ /dev/null
@@ -1,768 +0,0 @@
-/******************************************************************************
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implement OGRDataSourceWithTransaction class
- * Author:   Even Rouault, even dot rouault at spatialys dot com
- *
- ******************************************************************************
- * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
- *
- * SPDX-License-Identifier: MIT
- ****************************************************************************/
-
-#include "ogremulatedtransaction.h"
-#include "ogrlayerdecorator.h"
-#include <map>
-#include <set>
-
-class OGRDataSourceWithTransaction;
-
-class OGRLayerWithTransaction final : public OGRLayerDecorator
-{
-    CPL_DISALLOW_COPY_ASSIGN(OGRLayerWithTransaction)
-
-  protected:
-    friend class OGRDataSourceWithTransaction;
-
-    OGRDataSourceWithTransaction *m_poDS;
-    OGRFeatureDefn *m_poFeatureDefn;
-
-  public:
-    OGRLayerWithTransaction(OGRDataSourceWithTransaction *poDS,
-                            OGRLayer *poBaseLayer);
-    virtual ~OGRLayerWithTransaction() override;
-
-    virtual const char *GetName() override
-    {
-        return GetDescription();
-    }
-
-    virtual OGRFeatureDefn *GetLayerDefn() override;
-
-    virtual OGRErr CreateField(const OGRFieldDefn *poField,
-                               int bApproxOK = TRUE) override;
-    virtual OGRErr DeleteField(int iField) override;
-    virtual OGRErr ReorderFields(int *panMap) override;
-    virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
-                                  int nFlags) override;
-    virtual OGRErr
-    AlterGeomFieldDefn(int iField, const OGRGeomFieldDefn *poNewGeomFieldDefn,
-                       int nFlags) override;
-
-    virtual OGRErr CreateGeomField(const OGRGeomFieldDefn *poField,
-                                   int bApproxOK = TRUE) override;
-
-    virtual OGRFeature *GetNextFeature() override;
-    virtual OGRFeature *GetFeature(GIntBig nFID) override;
-    virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
-    virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
-    virtual OGRErr IUpsertFeature(OGRFeature *poFeature) override;
-
-    virtual OGRErr Rename(const char *pszNewName) override;
-};
-
-class OGRDataSourceWithTransaction final : public GDALDataset
-{
-    CPL_DISALLOW_COPY_ASSIGN(OGRDataSourceWithTransaction)
-
-  protected:
-    GDALDataset *m_poBaseDataSource;
-    IOGRTransactionBehaviour *m_poTransactionBehavior;
-    int m_bHasOwnershipDataSource;
-    int m_bHasOwnershipTransactionBehavior;
-    int m_bInTransaction;
-
-    std::map<CPLString, OGRLayerWithTransaction *> m_oMapLayers{};
-    std::set<OGRLayerWithTransaction *> m_oSetLayers{};
-    std::set<OGRLayer *> m_oSetExecuteSQLLayers{};
-
-    OGRLayer *WrapLayer(OGRLayer *poLayer);
-    void RemapLayers();
-
-  public:
-    OGRDataSourceWithTransaction(
-        GDALDataset *poBaseDataSource,
-        IOGRTransactionBehaviour *poTransactionBehaviour,
-        int bTakeOwnershipDataSource, int bTakeOwnershipTransactionBehavior);
-
-    virtual ~OGRDataSourceWithTransaction() override;
-
-    int IsInTransaction() const
-    {
-        return m_bInTransaction;
-    }
-
-    virtual int GetLayerCount() override;
-    virtual OGRLayer *GetLayer(int) override;
-    virtual OGRLayer *GetLayerByName(const char *) override;
-    virtual OGRErr DeleteLayer(int) override;
-    virtual bool IsLayerPrivate(int iLayer) const override;
-
-    virtual int TestCapability(const char *) override;
-
-    OGRLayer *ICreateLayer(const char *pszName,
-                           const OGRGeomFieldDefn *poGeomFieldDefn,
-                           CSLConstList papszOptions) override;
-
-    virtual OGRLayer *CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
-                                char **papszOptions = nullptr) override;
-
-    virtual OGRStyleTable *GetStyleTable() override;
-    virtual void SetStyleTableDirectly(OGRStyleTable *poStyleTable) override;
-
-    virtual void SetStyleTable(OGRStyleTable *poStyleTable) override;
-
-    virtual OGRLayer *ExecuteSQL(const char *pszStatement,
-                                 OGRGeometry *poSpatialFilter,
-                                 const char *pszDialect) override;
-    virtual void ReleaseResultSet(OGRLayer *poResultsSet) override;
-
-    virtual CPLErr FlushCache(bool bAtClosing) override;
-
-    virtual OGRErr StartTransaction(int bForce = FALSE) override;
-    virtual OGRErr CommitTransaction() override;
-    virtual OGRErr RollbackTransaction() override;
-
-    virtual std::vector<std::string>
-    GetFieldDomainNames(CSLConstList papszOptions = nullptr) const override;
-    virtual const OGRFieldDomain *
-    GetFieldDomain(const std::string &name) const override;
-    virtual bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
-                                std::string &failureReason) override;
-    virtual bool DeleteFieldDomain(const std::string &name,
-                                   std::string &failureReason) override;
-    virtual bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
-                                   std::string &failureReason) override;
-
-    std::vector<std::string>
-    GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
-
-    const GDALRelationship *
-    GetRelationship(const std::string &name) const override;
-
-    virtual std::shared_ptr<GDALGroup> GetRootGroup() const override;
-
-    virtual char **GetMetadata(const char *pszDomain = "") override;
-    virtual CPLErr SetMetadata(char **papszMetadata,
-                               const char *pszDomain = "") override;
-    virtual const char *GetMetadataItem(const char *pszName,
-                                        const char *pszDomain = "") override;
-    virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
-                                   const char *pszDomain = "") override;
-};
-
-/************************************************************************/
-/*                         ~IOGRTransactionBehaviour                    */
-/************************************************************************/
-
-IOGRTransactionBehaviour::~IOGRTransactionBehaviour()
-{
-}
-
-/************************************************************************/
-/*              OGRCreateEmulatedTransactionDataSourceWrapper()         */
-/************************************************************************/
-
-GDALDataset *OGRCreateEmulatedTransactionDataSourceWrapper(
-    GDALDataset *poBaseDataSource,
-    IOGRTransactionBehaviour *poTransactionBehaviour,
-    int bTakeOwnershipDataSource, int bTakeOwnershipTransactionBehavior)
-{
-    return new OGRDataSourceWithTransaction(
-        poBaseDataSource, poTransactionBehaviour, bTakeOwnershipDataSource,
-        bTakeOwnershipTransactionBehavior);
-}
-
-/************************************************************************/
-/*                      OGRDataSourceWithTransaction                    */
-/************************************************************************/
-
-OGRDataSourceWithTransaction::OGRDataSourceWithTransaction(
-    GDALDataset *poBaseDataSource,
-    IOGRTransactionBehaviour *poTransactionBehaviour,
-    int bTakeOwnershipDataSource, int bTakeOwnershipTransactionBehavior)
-    : m_poBaseDataSource(poBaseDataSource),
-      m_poTransactionBehavior(poTransactionBehaviour),
-      m_bHasOwnershipDataSource(bTakeOwnershipDataSource),
-      m_bHasOwnershipTransactionBehavior(bTakeOwnershipTransactionBehavior),
-      m_bInTransaction(FALSE)
-{
-}
-
-OGRDataSourceWithTransaction::~OGRDataSourceWithTransaction()
-{
-    std::set<OGRLayerWithTransaction *>::iterator oIter = m_oSetLayers.begin();
-    for (; oIter != m_oSetLayers.end(); ++oIter)
-        delete *oIter;
-
-    if (m_bHasOwnershipDataSource)
-        delete m_poBaseDataSource;
-    if (m_bHasOwnershipTransactionBehavior)
-        delete m_poTransactionBehavior;
-}
-
-OGRLayer *OGRDataSourceWithTransaction::WrapLayer(OGRLayer *poLayer)
-{
-    if (poLayer)
-    {
-        OGRLayer *poWrappedLayer = m_oMapLayers[poLayer->GetName()];
-        if (poWrappedLayer)
-            poLayer = poWrappedLayer;
-        else
-        {
-            OGRLayerWithTransaction *poMutexedLayer =
-                new OGRLayerWithTransaction(this, poLayer);
-            m_oMapLayers[poLayer->GetName()] = poMutexedLayer;
-            m_oSetLayers.insert(poMutexedLayer);
-            poLayer = poMutexedLayer;
-        }
-    }
-    return poLayer;
-}
-
-void OGRDataSourceWithTransaction::RemapLayers()
-{
-    std::set<OGRLayerWithTransaction *>::iterator oIter = m_oSetLayers.begin();
-    for (; oIter != m_oSetLayers.end(); ++oIter)
-    {
-        OGRLayerWithTransaction *poWrappedLayer = *oIter;
-        if (m_poBaseDataSource == nullptr)
-            poWrappedLayer->m_poDecoratedLayer = nullptr;
-        else
-        {
-            poWrappedLayer->m_poDecoratedLayer =
-                m_poBaseDataSource->GetLayerByName(poWrappedLayer->GetName());
-        }
-    }
-    m_oMapLayers.clear();
-}
-
-int OGRDataSourceWithTransaction::GetLayerCount()
-{
-    if (!m_poBaseDataSource)
-        return 0;
-    return m_poBaseDataSource->GetLayerCount();
-}
-
-OGRLayer *OGRDataSourceWithTransaction::GetLayer(int iIndex)
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return WrapLayer(m_poBaseDataSource->GetLayer(iIndex));
-}
-
-OGRLayer *OGRDataSourceWithTransaction::GetLayerByName(const char *pszName)
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return WrapLayer(m_poBaseDataSource->GetLayerByName(pszName));
-}
-
-OGRErr OGRDataSourceWithTransaction::DeleteLayer(int iIndex)
-{
-    if (!m_poBaseDataSource)
-        return OGRERR_FAILURE;
-    OGRLayer *poLayer = GetLayer(iIndex);
-    CPLString osName;
-    if (poLayer)
-        osName = poLayer->GetName();
-    OGRErr eErr = m_poBaseDataSource->DeleteLayer(iIndex);
-    if (eErr == OGRERR_NONE && !osName.empty())
-    {
-        std::map<CPLString, OGRLayerWithTransaction *>::iterator oIter =
-            m_oMapLayers.find(osName);
-        if (oIter != m_oMapLayers.end())
-        {
-            delete oIter->second;
-            m_oSetLayers.erase(oIter->second);
-            m_oMapLayers.erase(oIter);
-        }
-    }
-    return eErr;
-}
-
-bool OGRDataSourceWithTransaction::IsLayerPrivate(int iLayer) const
-{
-    if (!m_poBaseDataSource)
-        return false;
-    return m_poBaseDataSource->IsLayerPrivate(iLayer);
-}
-
-int OGRDataSourceWithTransaction::TestCapability(const char *pszCap)
-{
-    if (!m_poBaseDataSource)
-        return FALSE;
-
-    if (EQUAL(pszCap, ODsCEmulatedTransactions))
-        return TRUE;
-
-    return m_poBaseDataSource->TestCapability(pszCap);
-}
-
-OGRLayer *OGRDataSourceWithTransaction::ICreateLayer(
-    const char *pszName, const OGRGeomFieldDefn *poGeomFieldDefn,
-    CSLConstList papszOptions)
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return WrapLayer(m_poBaseDataSource->CreateLayer(pszName, poGeomFieldDefn,
-                                                     papszOptions));
-}
-
-OGRLayer *OGRDataSourceWithTransaction::CopyLayer(OGRLayer *poSrcLayer,
-                                                  const char *pszNewName,
-                                                  char **papszOptions)
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return WrapLayer(
-        m_poBaseDataSource->CopyLayer(poSrcLayer, pszNewName, papszOptions));
-}
-
-OGRStyleTable *OGRDataSourceWithTransaction::GetStyleTable()
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return m_poBaseDataSource->GetStyleTable();
-}
-
-void OGRDataSourceWithTransaction::SetStyleTableDirectly(
-    OGRStyleTable *poStyleTable)
-{
-    if (!m_poBaseDataSource)
-        return;
-    m_poBaseDataSource->SetStyleTableDirectly(poStyleTable);
-}
-
-void OGRDataSourceWithTransaction::SetStyleTable(OGRStyleTable *poStyleTable)
-{
-    if (!m_poBaseDataSource)
-        return;
-    m_poBaseDataSource->SetStyleTable(poStyleTable);
-}
-
-OGRLayer *OGRDataSourceWithTransaction::ExecuteSQL(const char *pszStatement,
-                                                   OGRGeometry *poSpatialFilter,
-                                                   const char *pszDialect)
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    OGRLayer *poLayer = m_poBaseDataSource->ExecuteSQL(
-        pszStatement, poSpatialFilter, pszDialect);
-    if (poLayer != nullptr)
-        m_oSetExecuteSQLLayers.insert(poLayer);
-    return poLayer;
-}
-
-void OGRDataSourceWithTransaction::ReleaseResultSet(OGRLayer *poResultsSet)
-{
-    if (!m_poBaseDataSource)
-        return;
-    m_oSetExecuteSQLLayers.erase(poResultsSet);
-    m_poBaseDataSource->ReleaseResultSet(poResultsSet);
-}
-
-CPLErr OGRDataSourceWithTransaction::FlushCache(bool bAtClosing)
-{
-    if (!m_poBaseDataSource)
-        return CE_None;
-    return m_poBaseDataSource->FlushCache(bAtClosing);
-}
-
-OGRErr OGRDataSourceWithTransaction::StartTransaction(int bForce)
-{
-    if (!m_poBaseDataSource)
-        return OGRERR_FAILURE;
-    if (!bForce)
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Transactions only supported in forced mode");
-        return OGRERR_UNSUPPORTED_OPERATION;
-    }
-    if (!m_oSetExecuteSQLLayers.empty())
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot start transaction while a layer returned by "
-                 "ExecuteSQL() hasn't been released.");
-        return OGRERR_FAILURE;
-    }
-    if (m_bInTransaction)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Transaction is already in progress");
-        return OGRERR_FAILURE;
-    }
-    int bHasReopenedDS = FALSE;
-    OGRErr eErr = m_poTransactionBehavior->StartTransaction(m_poBaseDataSource,
-                                                            bHasReopenedDS);
-    if (bHasReopenedDS)
-        RemapLayers();
-    if (eErr == OGRERR_NONE)
-        m_bInTransaction = TRUE;
-    return eErr;
-}
-
-OGRErr OGRDataSourceWithTransaction::CommitTransaction()
-{
-    if (!m_poBaseDataSource)
-        return OGRERR_FAILURE;
-    if (!m_bInTransaction)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "No transaction in progress");
-        return OGRERR_FAILURE;
-    }
-    if (!m_oSetExecuteSQLLayers.empty())
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot interrupt transaction while a layer returned by "
-                 "ExecuteSQL() hasn't been released.");
-        return OGRERR_FAILURE;
-    }
-    m_bInTransaction = FALSE;
-    int bHasReopenedDS = FALSE;
-    OGRErr eErr = m_poTransactionBehavior->CommitTransaction(m_poBaseDataSource,
-                                                             bHasReopenedDS);
-    if (bHasReopenedDS)
-        RemapLayers();
-    return eErr;
-}
-
-OGRErr OGRDataSourceWithTransaction::RollbackTransaction()
-{
-    if (!m_poBaseDataSource)
-        return OGRERR_FAILURE;
-    if (!m_bInTransaction)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "No transaction in progress");
-        return OGRERR_FAILURE;
-    }
-    if (!m_oSetExecuteSQLLayers.empty())
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot interrupt transaction while a layer returned by "
-                 "ExecuteSQL() hasn't been released.");
-        return OGRERR_FAILURE;
-    }
-    m_bInTransaction = FALSE;
-    int bHasReopenedDS = FALSE;
-    OGRErr eErr = m_poTransactionBehavior->RollbackTransaction(
-        m_poBaseDataSource, bHasReopenedDS);
-    if (bHasReopenedDS)
-        RemapLayers();
-    return eErr;
-}
-
-std::vector<std::string> OGRDataSourceWithTransaction::GetFieldDomainNames(
-    CSLConstList papszOptions) const
-{
-    if (!m_poBaseDataSource)
-        return std::vector<std::string>();
-    return m_poBaseDataSource->GetFieldDomainNames(papszOptions);
-}
-
-const OGRFieldDomain *
-OGRDataSourceWithTransaction::GetFieldDomain(const std::string &name) const
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return m_poBaseDataSource->GetFieldDomain(name);
-}
-
-bool OGRDataSourceWithTransaction::AddFieldDomain(
-    std::unique_ptr<OGRFieldDomain> &&domain, std::string &failureReason)
-{
-    if (!m_poBaseDataSource)
-        return false;
-    return m_poBaseDataSource->AddFieldDomain(std::move(domain), failureReason);
-}
-
-bool OGRDataSourceWithTransaction::DeleteFieldDomain(const std::string &name,
-                                                     std::string &failureReason)
-{
-    if (!m_poBaseDataSource)
-        return false;
-    return m_poBaseDataSource->DeleteFieldDomain(name, failureReason);
-}
-
-bool OGRDataSourceWithTransaction::UpdateFieldDomain(
-    std::unique_ptr<OGRFieldDomain> &&domain, std::string &failureReason)
-{
-    if (!m_poBaseDataSource)
-        return false;
-    return m_poBaseDataSource->UpdateFieldDomain(std::move(domain),
-                                                 failureReason);
-}
-
-std::vector<std::string> OGRDataSourceWithTransaction::GetRelationshipNames(
-    CSLConstList papszOptions) const
-{
-    if (!m_poBaseDataSource)
-        return {};
-    return m_poBaseDataSource->GetRelationshipNames(papszOptions);
-}
-
-const GDALRelationship *
-OGRDataSourceWithTransaction::GetRelationship(const std::string &name) const
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return m_poBaseDataSource->GetRelationship(name);
-}
-
-std::shared_ptr<GDALGroup> OGRDataSourceWithTransaction::GetRootGroup() const
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return m_poBaseDataSource->GetRootGroup();
-}
-
-char **OGRDataSourceWithTransaction::GetMetadata(const char *pszDomain)
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return m_poBaseDataSource->GetMetadata(pszDomain);
-}
-
-CPLErr OGRDataSourceWithTransaction::SetMetadata(char **papszMetadata,
-                                                 const char *pszDomain)
-{
-    if (!m_poBaseDataSource)
-        return CE_Failure;
-    return m_poBaseDataSource->SetMetadata(papszMetadata, pszDomain);
-}
-
-const char *OGRDataSourceWithTransaction::GetMetadataItem(const char *pszName,
-                                                          const char *pszDomain)
-{
-    if (!m_poBaseDataSource)
-        return nullptr;
-    return m_poBaseDataSource->GetMetadataItem(pszName, pszDomain);
-}
-
-CPLErr OGRDataSourceWithTransaction::SetMetadataItem(const char *pszName,
-                                                     const char *pszValue,
-                                                     const char *pszDomain)
-{
-    if (!m_poBaseDataSource)
-        return CE_Failure;
-    return m_poBaseDataSource->SetMetadataItem(pszName, pszValue, pszDomain);
-}
-
-/************************************************************************/
-/*                       OGRLayerWithTransaction                        */
-/************************************************************************/
-
-OGRLayerWithTransaction::OGRLayerWithTransaction(
-    OGRDataSourceWithTransaction *poDS, OGRLayer *poBaseLayer)
-    : OGRLayerDecorator(poBaseLayer, FALSE), m_poDS(poDS),
-      m_poFeatureDefn(nullptr)
-{
-}
-
-OGRLayerWithTransaction::~OGRLayerWithTransaction()
-{
-    if (m_poFeatureDefn)
-        m_poFeatureDefn->Release();
-}
-
-OGRFeatureDefn *OGRLayerWithTransaction::GetLayerDefn()
-{
-    if (!m_poDecoratedLayer)
-    {
-        if (m_poFeatureDefn == nullptr)
-        {
-            m_poFeatureDefn = new OGRFeatureDefn(GetDescription());
-            m_poFeatureDefn->Reference();
-        }
-        return m_poFeatureDefn;
-    }
-    else if (m_poFeatureDefn == nullptr)
-    {
-        OGRFeatureDefn *poSrcFeatureDefn = m_poDecoratedLayer->GetLayerDefn();
-        m_poFeatureDefn = poSrcFeatureDefn->Clone();
-        m_poFeatureDefn->Reference();
-    }
-    return m_poFeatureDefn;
-}
-
-OGRErr OGRLayerWithTransaction::CreateField(const OGRFieldDefn *poField,
-                                            int bApproxOK)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    int nFields = m_poDecoratedLayer->GetLayerDefn()->GetFieldCount();
-    OGRErr eErr = m_poDecoratedLayer->CreateField(poField, bApproxOK);
-    if (m_poFeatureDefn && eErr == OGRERR_NONE &&
-        m_poDecoratedLayer->GetLayerDefn()->GetFieldCount() == nFields + 1)
-    {
-        m_poFeatureDefn->AddFieldDefn(
-            m_poDecoratedLayer->GetLayerDefn()->GetFieldDefn(nFields));
-    }
-    return eErr;
-}
-
-OGRErr OGRLayerWithTransaction::CreateGeomField(const OGRGeomFieldDefn *poField,
-                                                int bApproxOK)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    int nFields = m_poDecoratedLayer->GetLayerDefn()->GetGeomFieldCount();
-    OGRErr eErr = m_poDecoratedLayer->CreateGeomField(poField, bApproxOK);
-    if (m_poFeatureDefn && eErr == OGRERR_NONE &&
-        m_poDecoratedLayer->GetLayerDefn()->GetGeomFieldCount() == nFields + 1)
-    {
-        m_poFeatureDefn->AddGeomFieldDefn(
-            m_poDecoratedLayer->GetLayerDefn()->GetGeomFieldDefn(nFields));
-    }
-    return eErr;
-}
-
-OGRErr OGRLayerWithTransaction::DeleteField(int iField)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    OGRErr eErr = m_poDecoratedLayer->DeleteField(iField);
-    if (m_poFeatureDefn && eErr == OGRERR_NONE)
-        m_poFeatureDefn->DeleteFieldDefn(iField);
-    return eErr;
-}
-
-OGRErr OGRLayerWithTransaction::ReorderFields(int *panMap)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    OGRErr eErr = m_poDecoratedLayer->ReorderFields(panMap);
-    if (m_poFeatureDefn && eErr == OGRERR_NONE)
-        m_poFeatureDefn->ReorderFieldDefns(panMap);
-    return eErr;
-}
-
-OGRErr OGRLayerWithTransaction::AlterFieldDefn(int iField,
-                                               OGRFieldDefn *poNewFieldDefn,
-                                               int nFlagsIn)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    OGRErr eErr =
-        m_poDecoratedLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
-    if (m_poFeatureDefn && eErr == OGRERR_NONE)
-    {
-        OGRFieldDefn *poSrcFieldDefn =
-            m_poDecoratedLayer->GetLayerDefn()->GetFieldDefn(iField);
-        OGRFieldDefn *poDstFieldDefn = m_poFeatureDefn->GetFieldDefn(iField);
-        poDstFieldDefn->SetName(poSrcFieldDefn->GetNameRef());
-        poDstFieldDefn->SetType(poSrcFieldDefn->GetType());
-        poDstFieldDefn->SetSubType(poSrcFieldDefn->GetSubType());
-        poDstFieldDefn->SetWidth(poSrcFieldDefn->GetWidth());
-        poDstFieldDefn->SetPrecision(poSrcFieldDefn->GetPrecision());
-        poDstFieldDefn->SetDefault(poSrcFieldDefn->GetDefault());
-        poDstFieldDefn->SetNullable(poSrcFieldDefn->IsNullable());
-        poDstFieldDefn->SetUnique(poSrcFieldDefn->IsUnique());
-        poDstFieldDefn->SetDomainName(poSrcFieldDefn->GetDomainName());
-        poDstFieldDefn->SetComment(poSrcFieldDefn->GetComment());
-    }
-    return eErr;
-}
-
-OGRErr OGRLayerWithTransaction::AlterGeomFieldDefn(
-    int iGeomField, const OGRGeomFieldDefn *poNewGeomFieldDefn, int nFlagsIn)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    OGRErr eErr = m_poDecoratedLayer->AlterGeomFieldDefn(
-        iGeomField, poNewGeomFieldDefn, nFlagsIn);
-    if (m_poFeatureDefn && eErr == OGRERR_NONE)
-    {
-        const auto poSrcFieldDefn =
-            m_poDecoratedLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomField);
-        auto poDstFieldDefn = m_poFeatureDefn->GetGeomFieldDefn(iGeomField);
-        poDstFieldDefn->SetName(poSrcFieldDefn->GetNameRef());
-        poDstFieldDefn->SetType(poSrcFieldDefn->GetType());
-        poDstFieldDefn->SetSpatialRef(poSrcFieldDefn->GetSpatialRef());
-        poDstFieldDefn->SetNullable(poSrcFieldDefn->IsNullable());
-    }
-    return eErr;
-}
-
-OGRFeature *OGRLayerWithTransaction::GetNextFeature()
-{
-    if (!m_poDecoratedLayer)
-        return nullptr;
-    OGRFeature *poSrcFeature = m_poDecoratedLayer->GetNextFeature();
-    if (!poSrcFeature)
-        return nullptr;
-    OGRFeature *poFeature = new OGRFeature(GetLayerDefn());
-    poFeature->SetFrom(poSrcFeature);
-    poFeature->SetFID(poSrcFeature->GetFID());
-    delete poSrcFeature;
-    return poFeature;
-}
-
-OGRFeature *OGRLayerWithTransaction::GetFeature(GIntBig nFID)
-{
-    if (!m_poDecoratedLayer)
-        return nullptr;
-    OGRFeature *poSrcFeature = m_poDecoratedLayer->GetFeature(nFID);
-    if (!poSrcFeature)
-        return nullptr;
-    OGRFeature *poFeature = new OGRFeature(GetLayerDefn());
-    poFeature->SetFrom(poSrcFeature);
-    poFeature->SetFID(poSrcFeature->GetFID());
-    delete poSrcFeature;
-    return poFeature;
-}
-
-OGRErr OGRLayerWithTransaction::ISetFeature(OGRFeature *poFeature)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    OGRFeature *poSrcFeature =
-        new OGRFeature(m_poDecoratedLayer->GetLayerDefn());
-    poSrcFeature->SetFrom(poFeature);
-    poSrcFeature->SetFID(poFeature->GetFID());
-    OGRErr eErr = m_poDecoratedLayer->SetFeature(poSrcFeature);
-    delete poSrcFeature;
-    return eErr;
-}
-
-OGRErr OGRLayerWithTransaction::ICreateFeature(OGRFeature *poFeature)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    OGRFeature *poSrcFeature =
-        new OGRFeature(m_poDecoratedLayer->GetLayerDefn());
-    poSrcFeature->SetFrom(poFeature);
-    poSrcFeature->SetFID(poFeature->GetFID());
-    OGRErr eErr = m_poDecoratedLayer->CreateFeature(poSrcFeature);
-    poFeature->SetFID(poSrcFeature->GetFID());
-    delete poSrcFeature;
-    return eErr;
-}
-
-OGRErr OGRLayerWithTransaction::IUpsertFeature(OGRFeature *poFeature)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    OGRFeature *poSrcFeature =
-        new OGRFeature(m_poDecoratedLayer->GetLayerDefn());
-    poSrcFeature->SetFrom(poFeature);
-    poSrcFeature->SetFID(poFeature->GetFID());
-    OGRErr eErr = m_poDecoratedLayer->UpsertFeature(poSrcFeature);
-    delete poSrcFeature;
-    return eErr;
-}
-
-OGRErr OGRLayerWithTransaction::Rename(const char *pszNewName)
-{
-    if (!m_poDecoratedLayer)
-        return OGRERR_FAILURE;
-    OGRErr eErr = m_poDecoratedLayer->Rename(pszNewName);
-    if (eErr == OGRERR_NONE)
-    {
-        SetDescription(m_poDecoratedLayer->GetDescription());
-        if (m_poFeatureDefn)
-            m_poFeatureDefn->SetName(
-                m_poDecoratedLayer->GetLayerDefn()->GetName());
-    }
-    return eErr;
-}
diff --git a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
deleted file mode 100644
index 0e1395504b73..000000000000
--- a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/******************************************************************************
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Defines OGRDataSourceWithTransaction class
- * Author:   Even Rouault, even dot rouault at spatialys dot com
- *
- ******************************************************************************
- * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
- *
- * SPDX-License-Identifier: MIT
- ****************************************************************************/
-
-#ifndef OGREMULATEDTRANSACTION_H_INCLUDED
-#define OGREMULATEDTRANSACTION_H_INCLUDED
-
-#include "ogrsf_frmts.h"
-
-/** IOGRTransactionBehaviour is an interface that a driver must implement
- *  to provide emulation of transactions.
- *
- * @since GDAL 2.0
- */
-class CPL_DLL IOGRTransactionBehaviour
-{
-  public:
-    virtual ~IOGRTransactionBehaviour();
-
-    /** Start a transaction.
-     *
-     * The implementation may update the poDSInOut reference by closing
-     * and reopening the datasource (or assigning it to NULL in case of error).
-     * In which case bOutHasReopenedDS must be set to TRUE.
-     *
-     * The implementation can for example backup the existing files/directories
-     * that compose the current datasource.
-     *
-     * @param poDSInOut datasource handle that may be modified
-     * @param bOutHasReopenedDS output boolean to indicate if datasource has
-     * been closed
-     * @return OGRERR_NONE in case of success
-     */
-    virtual OGRErr StartTransaction(GDALDataset *&poDSInOut,
-                                    int &bOutHasReopenedDS) = 0;
-
-    /** Commit a transaction.
-     *
-     * The implementation may update the poDSInOut reference by closing
-     * and reopening the datasource (or assigning it to NULL in case of error).
-     * In which case bOutHasReopenedDS must be set to TRUE.
-     *
-     * The implementation can for example remove the backup it may have done
-     * at StartTransaction() time.
-     *
-     * @param poDSInOut datasource handle that may be modified
-     * @param bOutHasReopenedDS output boolean to indicate if datasource has
-     * been closed
-     * @return OGRERR_NONE in case of success
-     */
-    virtual OGRErr CommitTransaction(GDALDataset *&poDSInOut,
-                                     int &bOutHasReopenedDS) = 0;
-
-    /** Rollback a transaction.
-     *
-     * The implementation may update the poDSInOut reference by closing
-     * and reopening the datasource (or assigning it to NULL in case of error).
-     * In which case bOutHasReopenedDS must be set to TRUE.
-     *
-     * The implementation can for example restore the backup it may have done
-     * at StartTransaction() time.
-     *
-     * @param poDSInOut datasource handle that may be modified
-     * @param bOutHasReopenedDS output boolean to indicate if datasource has
-     * been closed
-     * @return OGRERR_NONE in case of success
-     */
-    virtual OGRErr RollbackTransaction(GDALDataset *&poDSInOut,
-                                       int &bOutHasReopenedDS) = 0;
-};
-
-/** Returns a new datasource object that adds transactional behavior to an
- * existing datasource.
- *
- * The provided poTransactionBehaviour object should implement driver-specific
- * behavior for transactions.
- *
- * The generic mechanisms offered by the wrapper class do not cover concurrent
- * updates (though different datasource connections) to the same datasource
- * files.
- *
- * There are restrictions on what can be accomplished. For example it is not
- * allowed to have a unreleased layer returned by ExecuteSQL() before calling
- * StartTransaction(), CommitTransaction() or RollbackTransaction().
- *
- * Layer structural changes are not allowed after StartTransaction() if the
- * layer definition object has been returned previously with GetLayerDefn().
- *
- * @param poBaseDataSource the datasource to which to add transactional
- * behavior.
- * @param poTransactionBehaviour an implementation of the
- * IOGRTransactionBehaviour interface.
- * @param bTakeOwnershipDataSource whether the returned object should own the
- *                                 passed poBaseDataSource (and thus destroy it
- *                                 when it is destroyed itself).
- * @param bTakeOwnershipTransactionBehavior whether the returned object should
- * own the passed poTransactionBehaviour (and thus destroy it when it is
- * destroyed itself).
- * @return a new datasource handle
- * @since GDAL 2.0
- */
-GDALDataset CPL_DLL *OGRCreateEmulatedTransactionDataSourceWrapper(
-    GDALDataset *poBaseDataSource,
-    IOGRTransactionBehaviour *poTransactionBehaviour,
-    int bTakeOwnershipDataSource, int bTakeOwnershipTransactionBehavior);
-
-#endif  // OGREMULATEDTRANSACTION_H_INCLUDED