@@ -32,9 +32,11 @@ class QgsOgrFeatureIterator;
32
32
33
33
#include < gdal.h>
34
34
35
+ class QgsOgrLayer ;
36
+
35
37
/* *
36
38
\class QgsOgrProvider
37
- \brief Data provider for ESRI shapefiles
39
+ \brief Data provider for OGR datasources
38
40
*/
39
41
class QgsOgrProvider : public QgsVectorDataProvider
40
42
{
@@ -141,7 +143,7 @@ class QgsOgrProvider : public QgsVectorDataProvider
141
143
void recalculateFeatureCount ();
142
144
143
145
// ! Tell OGR, which fields to fetch in nextFeature/featureAtId (ie. which not to ignore)
144
- void setRelevantFields ( OGRLayerH ogrLayer, bool fetchGeometry, const QgsAttributeList &fetchAttributes );
146
+ void setRelevantFields ( bool fetchGeometry, const QgsAttributeList &fetchAttributes );
145
147
146
148
// ! Convert a QgsField to work with OGR
147
149
static bool convertField ( QgsField &field, const QTextCodec &encoding );
@@ -176,22 +178,27 @@ class QgsOgrProvider : public QgsVectorDataProvider
176
178
// ! Commits a transaction
177
179
bool commitTransaction ();
178
180
181
+ void addSubLayerDetailsToSubLayerList ( int i, QgsOgrLayer *layer ) const ;
182
+
179
183
QgsFields mAttributeFields ;
180
184
181
185
// ! Map of field index to default value
182
186
QMap<int , QString> mDefaultValues ;
183
187
184
188
bool mFirstFieldIsFid = false ;
185
- GDALDatasetH mGDALDataset = nullptr ;
186
189
mutable OGREnvelope *mExtent = nullptr ;
187
190
bool mForceRecomputeExtent = false ;
188
191
189
192
/* *
190
193
* This member variable receives the same value as extent_
191
194
in the method QgsOgrProvider::extent(). The purpose is to prevent a memory leak*/
192
195
mutable QgsRectangle mExtentRect ;
193
- OGRLayerH ogrLayer = nullptr ;
194
- OGRLayerH ogrOrigLayer = nullptr ;
196
+
197
+ // ! Current working layer (might be a SQL result layer if mSubsetString is set)
198
+ QgsOgrLayer *mOgrLayer = nullptr ;
199
+
200
+ // ! Original layer (not a SQL result layer)
201
+ QgsOgrLayer *mOgrOrigLayer = nullptr ;
195
202
196
203
// ! path to filename
197
204
QString mFilePath ;
@@ -217,9 +224,6 @@ class QgsOgrProvider : public QgsVectorDataProvider
217
224
// ! String used to define a subset of the layer
218
225
QString mSubsetString ;
219
226
220
- // GDAL Driver that was actually used to open the layer
221
- GDALDriverH mGDALDriver = nullptr ;
222
-
223
227
// Friendly name of the GDAL Driver that was actually used to open the layer
224
228
QString mGDALDriverName ;
225
229
@@ -237,8 +241,6 @@ class QgsOgrProvider : public QgsVectorDataProvider
237
241
// ! Calls OGR_L_SyncToDisk and recreates the spatial index if present
238
242
bool syncToDisc ();
239
243
240
- OGRLayerH setSubsetString ( OGRLayerH layer, GDALDatasetH ds );
241
-
242
244
friend class QgsOgrFeatureSource ;
243
245
244
246
// ! Whether the file is opened in write mode
@@ -266,9 +268,54 @@ class QgsOgrProvider : public QgsVectorDataProvider
266
268
bool doInitialActionsForEdition ();
267
269
};
268
270
269
-
271
+ /* *
272
+ \class QgsOgrProviderUtils
273
+ \brief Utility class with static methods
274
+ */
270
275
class QgsOgrProviderUtils
271
276
{
277
+ friend class QgsOgrLayer ;
278
+
279
+ // ! Identifies a dataset by name, updateMode and options
280
+ class DatasetIdentification
281
+ {
282
+ QString toString () const ;
283
+
284
+ public:
285
+ QString dsName;
286
+ bool updateMode = false ;
287
+ QStringList options;
288
+ DatasetIdentification () {}
289
+
290
+ bool operator < ( const DatasetIdentification &other ) const ;
291
+ };
292
+
293
+ // ! GDAL dataset objects and layers in use in it
294
+ class DatasetWithLayers
295
+ {
296
+ public:
297
+ QMutex mutex;
298
+ GDALDatasetH hDS = nullptr ;
299
+ QMap<QString, QgsOgrLayer *> setLayers;
300
+ int refCount = 0 ;
301
+
302
+ DatasetWithLayers (): mutex( QMutex::Recursive ) {}
303
+ };
304
+
305
+ // ! Global mutex for QgsOgrProviderUtils
306
+ static QMutex globalMutex;
307
+
308
+ // ! Map dataset identification to a list of corresponding DatasetWithLayers*
309
+ static QMap< DatasetIdentification, QList<DatasetWithLayers *> > mapSharedDS;
310
+
311
+ // ! Map a dataset name to the number of opened GDAL dataset objects on it (if opened with GDALOpenWrapper)
312
+ static QMap< QString, int > mapCountOpenedDS;
313
+
314
+ // ! Map a dataset name to its last modified data
315
+ static QMap< QString, QDateTime > mapDSNameToLastModifiedDate;
316
+
317
+ static bool canUseOpenedDatasets ( const QString &dsName );
318
+
272
319
public:
273
320
static void setRelevantFields ( OGRLayerH ogrLayer, int fieldCount, bool fetchGeometry, const QgsAttributeList &fetchAttributes, bool firstAttrIsFid );
274
321
static OGRLayerH setSubsetString ( OGRLayerH layer, GDALDatasetH ds, QTextCodec *encoding, const QString &subsetString, bool &origFidAdded );
@@ -279,8 +326,220 @@ class QgsOgrProviderUtils
279
326
*/
280
327
static QString quotedValue ( const QVariant &value );
281
328
282
- static GDALDatasetH GDALOpenWrapper ( const char *pszPath, bool bUpdate, bool bDisableReapck, GDALDriverH *phDriver );
329
+ // ! Wrapper for GDALOpenEx() that does a few lower level actions. Should be strictly paired with GDALCloseWrapper()
330
+ static GDALDatasetH GDALOpenWrapper ( const char *pszPath, bool bUpdate, char **papszOpenOptionsIn, GDALDriverH *phDriver );
331
+
332
+ // ! Wrapper for GDALClose()
283
333
static void GDALCloseWrapper ( GDALDatasetH mhDS );
334
+
335
+ // ! Open a layer given by name, potentially reusing an existing GDALDatasetH if it doesn't already use that layer. release() should be called when done with the object
336
+ static QgsOgrLayer *getLayer ( const QString &dsName,
337
+ const QString &layerName,
338
+ QString &errCause );
339
+
340
+
341
+ // ! Open a layer given by name, potentially reusing an existing GDALDatasetH if it has been opened with the same (updateMode, options) tuple and doesn't already use that layer. release() should be called when done with the object
342
+ static QgsOgrLayer *getLayer ( const QString &dsName,
343
+ bool updateMode,
344
+ const QStringList &options,
345
+ const QString &layerName,
346
+ QString &errCause );
347
+
348
+ // ! Open a layer given by index, potentially reusing an existing GDALDatasetH if it doesn't already use that layer. release() should be called when done with the object
349
+ static QgsOgrLayer *getLayer ( const QString &dsName,
350
+ int layerIndex,
351
+ QString &errCause );
352
+
353
+ // ! Open a layer given by index, potentially reusing an existing GDALDatasetH if it has been opened with the same (updateMode, options) tuple and doesn't already use that layer. release() should be called when done with the object
354
+ static QgsOgrLayer *getLayer ( const QString &dsName,
355
+ bool updateMode,
356
+ const QStringList &options,
357
+ int layerIndex,
358
+ QString &errCause );
359
+
360
+ // ! Return a QgsOgrLayer* with a SQL result layer
361
+ static QgsOgrLayer *getSqlLayer ( QgsOgrLayer *baseLayer, OGRLayerH hSqlLayer, const QString &sql );
362
+
363
+ // ! Release a QgsOgrLayer*
364
+ static void release ( QgsOgrLayer *&layer );
365
+
366
+ // ! Make sure that the existing pool of opened datasets on dsName is not accessible for new getLayer() attempts
367
+ static void invalidateCachedDatasets ( const QString &dsName );
368
+
369
+ // ! Return the string to provide to QgsOgrConnPool::instance() methods
370
+ static QString connectionPoolId ( const QString &dataSourceURI );
371
+ };
372
+
373
+
374
+ /* *
375
+ \class QgsOgrFeatureDefn
376
+ \brief Wrap a OGRFieldDefnH object in a thread-safe way
377
+ */
378
+ class QgsOgrFeatureDefn
379
+ {
380
+ friend class QgsOgrLayer ;
381
+
382
+ OGRFeatureDefnH hDefn = nullptr ;
383
+ QgsOgrLayer *layer = nullptr ;
384
+
385
+ QgsOgrFeatureDefn ();
386
+ ~QgsOgrFeatureDefn ();
387
+
388
+ OGRFeatureDefnH get ();
389
+ QMutex &mutex ();
390
+
391
+ public:
392
+
393
+ // ! Wrapper of OGR_FD_GetFieldCount
394
+ int GetFieldCount ();
395
+
396
+ // ! Wrapper of OGR_FD_GetFieldDefn
397
+ OGRFieldDefnH GetFieldDefn ( int );
398
+
399
+ // ! Wrapper of OGR_FD_GetFieldIndex
400
+ int GetFieldIndex ( const QByteArray & );
401
+
402
+ // ! Wrapper of OGR_FD_GetGeomFieldDefn
403
+ OGRGeomFieldDefnH GetGeomFieldDefn ( int idx );
404
+
405
+ // ! Wrapper of OGR_FD_GetGeomType
406
+ OGRwkbGeometryType GetGeomType ();
407
+
408
+ // ! Wrapper of OGR_F_Create
409
+ OGRFeatureH CreateFeature ();
410
+ };
411
+
412
+ /* *
413
+ \class QgsOgrLayer
414
+ \brief Wrap a OGRLayerH object in a thread-safe way
415
+ */
416
+ class QgsOgrLayer
417
+ {
418
+ friend class QgsOgrFeatureDefn ;
419
+ friend class QgsOgrProviderUtils ;
420
+
421
+ QgsOgrProviderUtils::DatasetIdentification ident;
422
+ bool isSqlLayer = false ;
423
+ QString layerName;
424
+ QString sql;
425
+ QgsOgrProviderUtils::DatasetWithLayers *ds = nullptr ;
426
+ OGRLayerH hLayer = nullptr ;
427
+ QgsOgrFeatureDefn oFDefn;
428
+
429
+ QgsOgrLayer ();
430
+ ~QgsOgrLayer ();
431
+
432
+ static QgsOgrLayer *CreateForLayer (
433
+ const QgsOgrProviderUtils::DatasetIdentification &ident,
434
+ const QString &layerName,
435
+ QgsOgrProviderUtils::DatasetWithLayers *ds,
436
+ OGRLayerH hLayer );
437
+
438
+ static QgsOgrLayer *CreateForSql (
439
+ const QgsOgrProviderUtils::DatasetIdentification &ident,
440
+ const QString &sql,
441
+ QgsOgrProviderUtils::DatasetWithLayers *ds,
442
+ OGRLayerH hLayer );
443
+
444
+ QMutex &mutex () { return ds->mutex ; }
445
+
446
+ public:
447
+
448
+ // ! Return GDALDriverH object for current dataset
449
+ GDALDriverH driver ();
450
+
451
+ // ! Return driver name for current dataset
452
+ QString driverName ();
453
+
454
+ // ! Return current dataset name
455
+ const QString &datasetName () const { return ident.dsName ; }
456
+
457
+ // ! Return dataset open mode
458
+ bool updateMode () const { return ident.updateMode ; }
459
+
460
+ // ! Return dataset open options
461
+ const QStringList &options () const { return ident.options ; }
462
+
463
+ // ! Return layer name
464
+ QByteArray name ();
465
+
466
+ // ! Wrapper of OGR_L_GetLayerCount
467
+ int GetLayerCount ();
468
+
469
+ // ! Wrapper of OGR_L_GetLayerCount
470
+ QByteArray GetFIDColumn ();
471
+
472
+ // ! Wrapper of OGR_L_GetLayerCount
473
+ OGRSpatialReferenceH GetSpatialRef ();
474
+
475
+ // ! Wrapper of OGR_L_GetLayerCount
476
+ void ResetReading ();
477
+
478
+ // ! Wrapper of OGR_L_GetLayerCount
479
+ OGRFeatureH GetNextFeature ();
480
+
481
+ // ! Wrapper of OGR_L_GetLayerCount
482
+ OGRFeatureH GetFeature ( GIntBig fid );
483
+
484
+ // ! Wrapper of OGR_L_GetLayerCount
485
+ QgsOgrFeatureDefn &GetLayerDefn ();
486
+
487
+ // ! Wrapper of OGR_L_GetLayerCount
488
+ GIntBig GetFeatureCount ( bool force = false );
489
+
490
+ // ! Wrapper of OGR_L_GetLayerCount
491
+ OGRErr GetExtent ( OGREnvelope *psExtent, bool bForce );
492
+
493
+ // ! Wrapper of OGR_L_GetLayerCount
494
+ OGRErr CreateFeature ( OGRFeatureH hFeature );
495
+
496
+ // ! Wrapper of OGR_L_GetLayerCount
497
+ OGRErr SetFeature ( OGRFeatureH hFeature );
498
+
499
+ // ! Wrapper of OGR_L_GetLayerCount
500
+ OGRErr DeleteFeature ( GIntBig fid );
501
+
502
+ // ! Wrapper of OGR_L_GetLayerCount
503
+ OGRErr CreateField ( OGRFieldDefnH hFieldDefn, bool bStrict );
504
+
505
+ // ! Wrapper of OGR_L_GetLayerCount
506
+ OGRErr DeleteField ( int iField );
507
+
508
+ // ! Wrapper of OGR_L_GetLayerCount
509
+ OGRErr AlterFieldDefn ( int iField, OGRFieldDefnH hNewFieldDefn, int flags );
510
+
511
+ // ! Wrapper of OGR_L_GetLayerCount
512
+ int TestCapability ( const char * );
513
+
514
+ // ! Wrapper of OGR_L_GetLayerCount
515
+ OGRErr StartTransaction ();
516
+
517
+ // ! Wrapper of OGR_L_GetLayerCount
518
+ OGRErr CommitTransaction ();
519
+
520
+ // ! Wrapper of OGR_L_GetLayerCount
521
+ OGRErr RollbackTransaction ();
522
+
523
+ // ! Wrapper of OGR_L_GetLayerCount
524
+ OGRErr SyncToDisk ();
525
+
526
+ // ! Wrapper of OGR_L_GetLayerCount
527
+ OGRGeometryH GetSpatialFilter ();
528
+
529
+ // ! Wrapper of OGR_L_GetLayerCount
530
+ void SetSpatialFilter ( OGRGeometryH );
531
+
532
+ // ! Return native GDALDatasetH object with the mutex to lock when using it
533
+ GDALDatasetH getDatasetHandleAndMutex ( QMutex *&mutex );
534
+
535
+ // ! Return native OGRLayerH object with the mutex to lock when using it
536
+ OGRLayerH getHandleAndMutex ( QMutex *&mutex );
537
+
538
+ // ! Wrapper of GDALDatasetReleaseResultSet( GDALDatasetExecuteSQL( ... ) )
539
+ void ExecuteSQLNoReturn ( const QByteArray &sql );
540
+
541
+ // ! Wrapper of GDALDatasetExecuteSQL(). Returned layer must be released with QgsOgrProviderUtils::release()
542
+ QgsOgrLayer *ExecuteSQL ( const QByteArray &sql );
284
543
};
285
544
286
545
// clazy:excludeall=qstring-allocations
0 commit comments