@@ -177,11 +177,54 @@ impl Dataset {
177
177
}
178
178
Ok ( Transaction :: new ( self ) )
179
179
}
180
+
181
+ /// Optionally start a transaction before running `func` for performance
182
+ ///
183
+ /// This uses transaction if the dataset supports it, otherwise it
184
+ /// runs the `func` function as it is on the dataset. If the
185
+ /// closure results in error, and it is a transaction, it is
186
+ /// rolled back.
187
+ pub fn maybe_batch ( & mut self , func : impl Fn ( & Dataset ) -> Result < ( ) > ) -> Result < ( ) > {
188
+ let force = 0 ; // since this is for speed
189
+ let rv = unsafe { gdal_sys:: GDALDatasetStartTransaction ( self . c_dataset ( ) , force) } ;
190
+ if rv == OGRErr :: OGRERR_UNSUPPORTED_OPERATION {
191
+ func ( self )
192
+ } else if rv == OGRErr :: OGRERR_NONE {
193
+ let res = func ( self ) ;
194
+ if res. is_ok ( ) {
195
+ let rv = unsafe { gdal_sys:: GDALDatasetCommitTransaction ( self . c_dataset ( ) ) } ;
196
+ if rv != OGRErr :: OGRERR_NONE {
197
+ Err ( GdalError :: OgrError {
198
+ err : rv,
199
+ method_name : "GDALDatasetCommitTransaction" ,
200
+ } )
201
+ } else {
202
+ res
203
+ }
204
+ } else {
205
+ let rv = unsafe { gdal_sys:: GDALDatasetRollbackTransaction ( self . c_dataset ( ) ) } ;
206
+ if rv != OGRErr :: OGRERR_NONE {
207
+ Err ( GdalError :: OgrError {
208
+ err : rv,
209
+ method_name : "GDALDatasetRollbackTransaction" ,
210
+ } )
211
+ } else {
212
+ res
213
+ }
214
+ }
215
+ } else {
216
+ // transaction supported but failed
217
+ Err ( GdalError :: OgrError {
218
+ err : rv,
219
+ method_name : "GDALDatasetStartTransaction" ,
220
+ } )
221
+ }
222
+ }
180
223
}
181
224
182
225
#[ cfg( test) ]
183
226
mod tests {
184
- use crate :: test_utils:: { fixture, open_gpkg_for_update} ;
227
+ use crate :: test_utils:: { fixture, open_dataset_for_update , open_gpkg_for_update} ;
185
228
use crate :: vector:: { Geometry , LayerAccess } ;
186
229
use crate :: Dataset ;
187
230
@@ -241,4 +284,30 @@ mod tests {
241
284
let mut ds = Dataset :: open ( fixture ( "roads.geojson" ) ) . unwrap ( ) ;
242
285
assert ! ( ds. start_transaction( ) . is_err( ) ) ;
243
286
}
287
+
288
+ #[ test]
289
+ fn test_maybe_batch ( ) {
290
+ let ( _temp_path, mut ds) = open_gpkg_for_update ( & fixture ( "poly.gpkg" ) ) ;
291
+ let orig_feature_count = ds. layer ( 0 ) . unwrap ( ) . feature_count ( ) ;
292
+
293
+ let res = ds. maybe_batch ( |d| {
294
+ let mut layer = d. layer ( 0 ) . unwrap ( ) ;
295
+ layer. create_feature ( polygon ( ) )
296
+ } ) ;
297
+ assert ! ( res. is_ok( ) ) ;
298
+ assert_eq ! ( ds. layer( 0 ) . unwrap( ) . feature_count( ) , orig_feature_count + 1 ) ;
299
+ }
300
+
301
+ #[ test]
302
+ fn test_maybe_transaction_unsupported ( ) {
303
+ let ( _temp_path, mut ds) = open_dataset_for_update ( & fixture ( "roads.geojson" ) ) ;
304
+ let orig_feature_count = ds. layer ( 0 ) . unwrap ( ) . feature_count ( ) ;
305
+
306
+ let res = ds. maybe_batch ( |d| {
307
+ let mut layer = d. layer ( 0 ) . unwrap ( ) ;
308
+ layer. create_feature ( polygon ( ) )
309
+ } ) ;
310
+ assert ! ( res. is_ok( ) ) ;
311
+ assert_eq ! ( ds. layer( 0 ) . unwrap( ) . feature_count( ) , orig_feature_count + 1 ) ;
312
+ }
244
313
}
0 commit comments