/
qgsogrproviderutils.h
498 lines (378 loc) · 16.5 KB
/
qgsogrproviderutils.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
/***************************************************************************
qgsogrproviderutils.h
begin : June 2021
copyright : (C) 2021 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSOGRPROVIDERUTILS_H
#define QGSOGRPROVIDERUTILS_H
#include "qgis_core.h"
#include "qgswkbtypes.h"
#include "qgsvectordataprovider.h"
#include <gdal.h>
#include <QString>
#include <QStringList>
#include <QMap>
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
#include <QMutex>
#else
#include <QRecursiveMutex>
#endif
class QgsOgrLayer;
class QgsCoordinateReferenceSystem;
class QgsProviderSublayerDetails;
///@cond PRIVATE
#define SIP_NO_FILE
/**
* Releases a QgsOgrLayer
*/
struct QgsOgrLayerReleaser
{
/**
* Releases a QgsOgrLayer \a layer.
*/
void operator()( QgsOgrLayer *layer );
};
/**
* Scoped QgsOgrLayer.
*/
using QgsOgrLayerUniquePtr = std::unique_ptr< QgsOgrLayer, QgsOgrLayerReleaser>;
class QgsOgrDataset;
/**
* Scoped QgsOgrDataset.
*/
using QgsOgrDatasetSharedPtr = std::shared_ptr< QgsOgrDataset>;
/**
* \class QgsOgrProviderUtils
* \brief Utility class with static methods
*/
class CORE_EXPORT QgsOgrProviderUtils
{
friend class QgsOgrDataset;
friend class QgsOgrLayer;
//! Identifies a dataset by name, updateMode and options
class DatasetIdentification
{
QString toString() const;
public:
QString dsName;
bool updateMode = false;
QStringList options;
DatasetIdentification() = default;
bool operator< ( const DatasetIdentification &other ) const;
};
//! GDAL dataset objects and layers in use in it
class DatasetWithLayers
{
public:
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QMutex mutex;
#else
QRecursiveMutex mutex;
#endif
GDALDatasetH hDS = nullptr;
QMap<QString, QgsOgrLayer *> setLayers;
int refCount = 0;
bool canBeShared = true;
DatasetWithLayers()
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
: mutex( QMutex::Recursive )
#endif
{}
};
//! Map dataset identification to a list of corresponding DatasetWithLayers*
static QMap< DatasetIdentification, QList<DatasetWithLayers *> > sMapSharedDS;
static bool canUseOpenedDatasets( const QString &dsName );
static void releaseInternal( const DatasetIdentification &ident,
DatasetWithLayers *ds,
bool removeFromDatasetList );
static DatasetWithLayers *createDatasetWithLayers(
const QString &dsName,
bool updateMode,
const QStringList &options,
const QString &layerName,
const DatasetIdentification &ident,
QgsOgrLayerUniquePtr &layer,
QString &errCause );
public:
static QString fileVectorFilters();
static QString databaseDrivers();
static QString protocolDrivers();
static QString directoryDrivers();
static QStringList fileExtensions();
static QStringList directoryExtensions();
static QStringList wildcards();
/**
* Creates an empty data source
* \param uri location to store the file(s)
* \param format data format (e.g. "ESRI Shapefile")
* \param vectortype point/line/polygon or multitypes
* \param attributes a list of name/type pairs for the initial attributes
* \return TRUE in case of success
*/
static bool createEmptyDataSource( const QString &uri,
const QString &format,
const QString &encoding,
QgsWkbTypes::Type vectortype,
const QList< QPair<QString, QString> > &attributes,
const QgsCoordinateReferenceSystem &srs,
QString &errorMessage );
static bool deleteLayer( const QString &uri, QString &errCause );
//! Inject credentials into the dsName (if any)
static QString expandAuthConfig( const QString &dsName );
static void setRelevantFields( OGRLayerH ogrLayer, int fieldCount,
bool fetchGeometry,
const QgsAttributeList &fetchAttributes,
bool firstAttrIsFid,
const QString &subsetString );
/**
* Sets a subset string for an OGR \a layer.
* Might return either layer, or a new OGR SQL result layer
*/
static OGRLayerH setSubsetString( OGRLayerH layer, GDALDatasetH ds, QTextCodec *encoding, const QString &subsetString );
static QByteArray quotedIdentifier( QByteArray field, const QString &driverName );
/**
* Quote a value for placement in a SQL string.
*/
static QString quotedValue( const QVariant &value );
//! Wrapper for GDALOpenEx() that does a few lower level actions. Should be strictly paired with GDALCloseWrapper()
static GDALDatasetH GDALOpenWrapper( const char *pszPath, bool bUpdate, char **papszOpenOptionsIn, GDALDriverH *phDriver );
//! Wrapper for GDALClose()
static void GDALCloseWrapper( GDALDatasetH mhDS );
//! Return a QgsOgrDataset wrapping an already opened GDALDataset. Typical use: by QgsOgrTransaction
static QgsOgrDatasetSharedPtr getAlreadyOpenedDataset( const QString &dsName );
//! Open a layer given by name, potentially reusing an existing GDALDatasetH if it doesn't already use that layer.
static QgsOgrLayerUniquePtr getLayer( const QString &dsName,
const QString &layerName,
QString &errCause );
//! 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.
static QgsOgrLayerUniquePtr getLayer( const QString &dsName,
bool updateMode,
const QStringList &options,
const QString &layerName,
QString &errCause,
bool checkModificationDateAgainstCache );
//! Open a layer given by index, potentially reusing an existing GDALDatasetH if it doesn't already use that layer.
static QgsOgrLayerUniquePtr getLayer( const QString &dsName,
int layerIndex,
QString &errCause );
//! 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.
static QgsOgrLayerUniquePtr getLayer( const QString &dsName,
bool updateMode,
const QStringList &options,
int layerIndex,
QString &errCause,
bool checkModificationDateAgainstCache );
//! Returns a QgsOgrLayer* with a SQL result layer
static QgsOgrLayerUniquePtr getSqlLayer( QgsOgrLayer *baseLayer, OGRLayerH hSqlLayer, const QString &sql );
//! Release a QgsOgrLayer*
static void release( QgsOgrLayer *&layer );
//! Release a QgsOgrDataset*
static void releaseDataset( QgsOgrDataset *&ds );
//! Make sure that the existing pool of opened datasets on dsName is not accessible for new getLayer() attempts
static void invalidateCachedDatasets( const QString &dsName );
//! Returns the string to provide to QgsOgrConnPool::instance() methods
static QString connectionPoolId( const QString &dataSourceURI, bool datasetSharedAmongLayers );
//! Invalidate the cached last modified date of a dataset
static void invalidateCachedLastModifiedDate( const QString &dsName );
//! Converts a QGIS WKB type to the corresponding OGR wkb type
static OGRwkbGeometryType ogrTypeFromQgisType( QgsWkbTypes::Type type );
//! Converts a OGR WKB type to the corresponding QGIS wkb type
static QgsWkbTypes::Type qgisTypeFromOgrType( OGRwkbGeometryType type );
//! Conerts a string to an OGR WKB geometry type
static OGRwkbGeometryType ogrWkbGeometryTypeFromName( const QString &typeName );
//! Gets single flatten geometry type
static OGRwkbGeometryType ogrWkbSingleFlatten( OGRwkbGeometryType type );
static QString ogrWkbGeometryTypeName( OGRwkbGeometryType type );
static QString analyzeURI( QString const &uri,
bool &isSubLayer,
int &layerIndex,
QString &layerName,
QString &subsetString,
OGRwkbGeometryType &ogrGeometryTypeFilter,
QStringList &openOptions );
//! Whether a driver can share the same dataset handle among different layers
static bool canDriverShareSameDatasetAmongLayers( const QString &driverName );
//! Whether a driver can share the same dataset handle among different layers
static bool canDriverShareSameDatasetAmongLayers( const QString &driverName,
bool updateMode,
const QString &dsName );
static QList<QgsProviderSublayerDetails> querySubLayerList( int i, QgsOgrLayer *layer, const QString &driverName, Qgis::SublayerQueryFlags flags, bool isSubLayer,
const QString &baseUri, bool hasSingleLayerOnly, QgsFeedback *feedback = nullptr );
};
/**
* \class QgsOgrDataset
* \brief Wrap a GDALDatasetH object in a thread-safe way
*/
class QgsOgrDataset
{
friend class QgsOgrProviderUtils;
friend class QgsOgrTransaction;
QgsOgrProviderUtils::DatasetIdentification mIdent;
QgsOgrProviderUtils::DatasetWithLayers *mDs;
QgsOgrDataset() = default;
~QgsOgrDataset() = default;
public:
static QgsOgrDatasetSharedPtr create( const QgsOgrProviderUtils::DatasetIdentification &ident,
QgsOgrProviderUtils::DatasetWithLayers *ds );
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QMutex &mutex() { return mDs->mutex; }
#else
QRecursiveMutex &mutex() { return mDs->mutex; }
#endif
bool executeSQLNoReturn( const QString &sql );
OGRLayerH getLayerFromNameOrIndex( const QString &layerName, int layerIndex );
void releaseResultSet( OGRLayerH hSqlLayer );
};
/**
* \class QgsOgrFeatureDefn
* \brief Wrap a OGRFieldDefnH object in a thread-safe way
*/
class QgsOgrFeatureDefn
{
friend class QgsOgrLayer;
OGRFeatureDefnH hDefn = nullptr;
QgsOgrLayer *layer = nullptr;
QgsOgrFeatureDefn() = default;
~QgsOgrFeatureDefn() = default;
OGRFeatureDefnH get();
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QMutex &mutex();
#else
QRecursiveMutex &mutex();
#endif
public:
//! Wrapper of OGR_FD_GetFieldCount
int GetFieldCount();
//! Wrapper of OGR_FD_GetFieldDefn
OGRFieldDefnH GetFieldDefn( int );
//! Wrapper of OGR_FD_GetFieldIndex
int GetFieldIndex( const QByteArray & );
//! Wrapper of OGR_FD_GetGeomFieldCount
int GetGeomFieldCount();
//! Wrapper of OGR_FD_GetGeomFieldDefn
OGRGeomFieldDefnH GetGeomFieldDefn( int idx );
//! Wrapper of OGR_FD_GetGeomType
OGRwkbGeometryType GetGeomType();
//! Wrapper of OGR_F_Create
OGRFeatureH CreateFeature();
};
/**
* \class QgsOgrLayer
* \brief Wrap a OGRLayerH object in a thread-safe way
*/
class QgsOgrLayer
{
friend class QgsOgrFeatureDefn;
friend class QgsOgrProviderUtils;
QgsOgrProviderUtils::DatasetIdentification ident;
bool isSqlLayer = false;
QString layerName;
QString sql; // not really used. Just set at QgsOgrLayer::CreateForLayer() time
QgsOgrProviderUtils::DatasetWithLayers *ds = nullptr;
OGRLayerH hLayer = nullptr;
QgsOgrFeatureDefn oFDefn;
QgsOgrLayer();
~QgsOgrLayer() = default;
static QgsOgrLayerUniquePtr CreateForLayer(
const QgsOgrProviderUtils::DatasetIdentification &ident,
const QString &layerName,
QgsOgrProviderUtils::DatasetWithLayers *ds,
OGRLayerH hLayer );
static QgsOgrLayerUniquePtr CreateForSql(
const QgsOgrProviderUtils::DatasetIdentification &ident,
const QString &sql,
QgsOgrProviderUtils::DatasetWithLayers *ds,
OGRLayerH hLayer );
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QMutex &mutex() { return ds->mutex; }
#else
QRecursiveMutex &mutex() { return ds->mutex; }
#endif
public:
//! Returns GDALDriverH object for current dataset
GDALDriverH driver();
//! Returns driver name for current dataset
QString driverName();
//! Returns current dataset name
const QString &datasetName() const { return ident.dsName; }
//! Returns dataset open mode
bool updateMode() const { return ident.updateMode; }
//! Returns dataset open options
const QStringList &options() const { return ident.options; }
//! Returns layer name
QByteArray name();
//! Wrapper of OGR_L_GetLayerCount
int GetLayerCount();
//! Wrapper of OGR_L_GetLayerCount
QByteArray GetFIDColumn();
//! Wrapper of OGR_L_GetLayerCount
OGRSpatialReferenceH GetSpatialRef();
//! Wrapper of OGR_L_GetLayerCount
void ResetReading();
//! Wrapper of OGR_L_GetLayerCount
OGRFeatureH GetNextFeature();
//! Wrapper of OGR_L_GetLayerCount
OGRFeatureH GetFeature( GIntBig fid );
//! Wrapper of OGR_L_GetLayerCount
QgsOgrFeatureDefn &GetLayerDefn();
//! Wrapper of OGR_L_GetLayerCount
GIntBig GetFeatureCount( bool force = false );
//! Return an approximate feature count
GIntBig GetApproxFeatureCount();
//! Wrapper of OGR_L_GetLayerCount
OGRErr GetExtent( OGREnvelope *psExtent, bool bForce );
//! Wrapper of OGR_L_GetLayerCount
OGRErr CreateFeature( OGRFeatureH hFeature );
//! Wrapper of OGR_L_GetLayerCount
OGRErr SetFeature( OGRFeatureH hFeature );
//! Wrapper of OGR_L_GetLayerCount
OGRErr DeleteFeature( GIntBig fid );
//! Wrapper of OGR_L_GetLayerCount
OGRErr CreateField( OGRFieldDefnH hFieldDefn, bool bStrict );
//! Wrapper of OGR_L_GetLayerCount
OGRErr DeleteField( int iField );
//! Wrapper of OGR_L_GetLayerCount
OGRErr AlterFieldDefn( int iField, OGRFieldDefnH hNewFieldDefn, int flags );
//! Wrapper of OGR_L_GetLayerCount
int TestCapability( const char * );
//! Wrapper of OGR_L_GetLayerCount
OGRErr StartTransaction();
//! Wrapper of OGR_L_GetLayerCount
OGRErr CommitTransaction();
//! Wrapper of OGR_L_GetLayerCount
OGRErr RollbackTransaction();
//! Wrapper of OGR_L_GetLayerCount
OGRErr SyncToDisk();
//! Wrapper of OGR_L_GetLayerCount
OGRGeometryH GetSpatialFilter();
//! Wrapper of OGR_L_GetLayerCount
void SetSpatialFilter( OGRGeometryH );
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
//! Returns native GDALDatasetH object with the mutex to lock when using it
GDALDatasetH getDatasetHandleAndMutex( QMutex *&mutex );
//! Returns native OGRLayerH object with the mutex to lock when using it
OGRLayerH getHandleAndMutex( QMutex *&mutex );
#else
//! Returns native GDALDatasetH object with the mutex to lock when using it
GDALDatasetH getDatasetHandleAndMutex( QRecursiveMutex *&mutex );
//! Returns native OGRLayerH object with the mutex to lock when using it
OGRLayerH getHandleAndMutex( QRecursiveMutex *&mutex );
#endif
//! Wrapper of GDALDatasetReleaseResultSet( GDALDatasetExecuteSQL( ... ) )
void ExecuteSQLNoReturn( const QByteArray &sql );
//! Wrapper of GDALDatasetExecuteSQL().
QgsOgrLayerUniquePtr ExecuteSQL( const QByteArray &sql );
// Wrapper of GDALGetMetadataItem()
QString GetMetadataItem( const QString &key, const QString &domain = QString() );
};
///@endcond
#endif // QGSOGRPROVIDERUTILS_H