Skip to content

Commit 6715441

Browse files
landamrouault
authored andcommitted
OGR data provider: use transactions when changing attributes and geometries (if possible) (fixes #16216)
Cherry picked from 16a421c
1 parent af74635 commit 6715441

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/providers/ogr/qgsogrprovider.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,31 @@ bool QgsOgrProvider::renameAttributes( const QgsFieldNameMap& renamedAttributes
15211521
#endif
15221522
}
15231523

1524+
bool QgsOgrProvider::startTransaction()
1525+
{
1526+
bool inTransaction = false;
1527+
if ( OGR_L_TestCapability( ogrLayer, OLCTransactions ) )
1528+
{
1529+
// A transaction might already be active, so be robust on failed
1530+
// StartTransaction.
1531+
CPLPushErrorHandler( CPLQuietErrorHandler );
1532+
inTransaction = ( OGR_L_StartTransaction( ogrLayer ) == OGRERR_NONE );
1533+
CPLPopErrorHandler();
1534+
}
1535+
return inTransaction;
1536+
}
1537+
1538+
1539+
bool QgsOgrProvider::commitTransaction()
1540+
{
1541+
if ( OGR_L_CommitTransaction( ogrLayer ) != OGRERR_NONE )
1542+
{
1543+
pushError( tr( "OGR error committing transaction: %1" ).arg( CPLGetLastErrorMsg() ) );
1544+
return false;
1545+
}
1546+
return true;
1547+
}
1548+
15241549

15251550
bool QgsOgrProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_map )
15261551
{
@@ -1534,6 +1559,8 @@ bool QgsOgrProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
15341559

15351560
setRelevantFields( ogrLayer, true, attributeIndexes() );
15361561

1562+
const bool inTransaction = startTransaction();
1563+
15371564
for ( QgsChangedAttributesMap::const_iterator it = attr_map.begin(); it != attr_map.end(); ++it )
15381565
{
15391566
QgsFeatureId fid = it.key();
@@ -1649,6 +1676,11 @@ bool QgsOgrProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
16491676
OGR_F_Destroy( of );
16501677
}
16511678

1679+
if ( inTransaction )
1680+
{
1681+
commitTransaction();
1682+
}
1683+
16521684
if ( OGR_L_SyncToDisk( ogrLayer ) != OGRERR_NONE )
16531685
{
16541686
pushError( tr( "OGR error syncing to disk: %1" ).arg( CPLGetLastErrorMsg() ) );
@@ -1664,6 +1696,8 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
16641696

16651697
setRelevantFields( ogrLayer, true, attributeIndexes() );
16661698

1699+
const bool inTransaction = startTransaction();
1700+
16671701
for ( QgsGeometryMap::const_iterator it = geometry_map.constBegin(); it != geometry_map.constEnd(); ++it )
16681702
{
16691703
if ( FID_TO_NUMBER( it.key() ) > std::numeric_limits<long>::max() )
@@ -1731,6 +1765,12 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
17311765

17321766
OGR_F_Destroy( theOGRFeature );
17331767
}
1768+
1769+
if ( inTransaction )
1770+
{
1771+
commitTransaction();
1772+
}
1773+
17341774
QgsOgrConnPool::instance()->invalidateConnections( dataSourceUri() );
17351775
return syncToDisc();
17361776
}

src/providers/ogr/qgsogrprovider.h

+7
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,13 @@ class QgsOgrProvider : public QgsVectorDataProvider
305305
private:
306306
unsigned char *getGeometryPointer( OGRFeatureH fet );
307307
QString ogrWkbGeometryTypeName( OGRwkbGeometryType type ) const;
308+
309+
//! Starts a transaction if possible and return true in that case
310+
bool startTransaction();
311+
312+
//! Commits a transaction
313+
bool commitTransaction();
314+
308315
QgsFields mAttributeFields;
309316
bool mFirstFieldIsFid;
310317
OGRDataSourceH ogrDataSource;

0 commit comments

Comments
 (0)