/
qgsspatialiteprovider.h
386 lines (302 loc) · 13.2 KB
/
qgsspatialiteprovider.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
/***************************************************************************
qgsspatialiteprovider.h Data provider for SpatiaLite DBMS
begin : Dec 2008
copyright : (C) 2008 Sandro Furieri
email : a.furieri@lqt.it
***************************************************************************/
/***************************************************************************
* *
* 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 QGSSPATIALITEPROVIDER_H
#define QGSSPATIALITEPROVIDER_H
extern "C"
{
#include <sys/types.h>
#include <sqlite3.h>
#include <spatialite/gaiageo.h>
#include <spatialite.h>
}
#include "qgsvectordataprovider.h"
#include "qgsrectangle.h"
#include "qgsvectorlayerexporter.h"
#include "qgsfields.h"
#include "qgswkbtypes.h"
#include <list>
#include <queue>
#include <fstream>
#include <set>
class QgsFeature;
class QgsField;
class QgsSqliteHandle;
class QgsSpatiaLiteFeatureIterator;
#include "qgsdatasourceuri.h"
/**
\class QgsSpatiaLiteProvider
\brief Data provider for SQLite/SpatiaLite layers.
This provider implements the
interface defined in the QgsDataProvider class to provide access to spatial
data residing in a SQLite/SpatiaLite enabled database.
*/
class QgsSpatiaLiteProvider: public QgsVectorDataProvider
{
Q_OBJECT
public:
//! Import a vector layer into the database
static QgsVectorLayerExporter::ExportError createEmptyLayer(
const QString &uri,
const QgsFields &fields,
QgsWkbTypes::Type wkbType,
const QgsCoordinateReferenceSystem &srs,
bool overwrite,
QMap<int, int> *oldToNewAttrIdxMap,
QString *errorMessage = nullptr,
const QMap<QString, QVariant> *options = nullptr
);
/**
* Constructor of the vector provider
* \param uri uniform resource locator (URI) for a dataset
*/
explicit QgsSpatiaLiteProvider( QString const &uri = QString() );
virtual ~ QgsSpatiaLiteProvider();
virtual QgsAbstractFeatureSource *featureSource() const override;
virtual QString storageType() const override;
virtual QgsCoordinateReferenceSystem crs() const override;
virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest &request ) const override;
virtual QString subsetString() const override;
virtual bool setSubsetString( const QString &theSQL, bool updateFeatureCount = true ) override;
virtual bool supportsSubsetString() const override { return true; }
QgsWkbTypes::Type wkbType() const override;
/**
* Return the number of layers for the current data source
*
* \note Should this be subLayerCount() instead?
*/
size_t layerCount() const;
long featureCount() const override;
virtual QgsRectangle extent() const override;
virtual void updateExtents() override;
QgsFields fields() const override;
QVariant minimumValue( int index ) const override;
QVariant maximumValue( int index ) const override;
virtual QSet<QVariant> uniqueValues( int index, int limit = -1 ) const override;
virtual QStringList uniqueStringsMatching( int index, const QString &substring, int limit = -1,
QgsFeedback *feedback = nullptr ) const override;
bool isValid() const override;
virtual bool isSaveAndLoadStyleToDatabaseSupported() const override { return true; }
bool addFeatures( QgsFeatureList &flist, QgsFeatureSink::Flags flags = nullptr ) override;
bool deleteFeatures( const QgsFeatureIds &id ) override;
bool truncate() override;
bool addAttributes( const QList<QgsField> &attributes ) override;
bool changeAttributeValues( const QgsChangedAttributesMap &attr_map ) override;
bool changeGeometryValues( const QgsGeometryMap &geometry_map ) override;
QgsVectorDataProvider::Capabilities capabilities() const override;
QVariant defaultValue( int fieldId ) const override;
virtual bool skipConstraintCheck( int fieldIndex, QgsFieldConstraints::Constraint constraint, const QVariant &value = QVariant() ) const override;
bool createAttributeIndex( int field ) override;
/**
* The SpatiaLite provider does its own transforms so we return
* true for the following three functions to indicate that transforms
* should not be handled by the QgsCoordinateTransform object. See the
* documentation on QgsVectorDataProvider for details on these functions.
*/
// XXX For now we have disabled native transforms in the SpatiaLite
// (following the PostgreSQL provider example)
bool supportsNativeTransform()
{
return false;
}
QString name() const override;
QString description() const override;
QgsAttributeList pkAttributeIndexes() const override;
void invalidateConnections( const QString &connection ) override;
QList<QgsRelation> discoverRelations( const QgsVectorLayer *self, const QList<QgsVectorLayer *> &layers ) const override;
// static functions
static void convertToGeosWKB( const unsigned char *blob, int blob_size,
unsigned char **wkb, int *geom_size );
static int computeMultiWKB3Dsize( const unsigned char *p_in, int little_endian,
int endian_arch );
static QString quotedIdentifier( QString id );
static QString quotedValue( QString value );
struct SLFieldNotFound {}; //! Exception to throw
struct SLException
{
explicit SLException( char *msg ) : errMsg( msg )
{
}
SLException( const SLException &e ) : errMsg( e.errMsg )
{
}
~SLException()
{
if ( errMsg )
sqlite3_free( errMsg );
}
SLException &operator=( const SLException &other ) = delete;
QString errorMessage() const
{
return errMsg ? QString::fromUtf8( errMsg ) : QStringLiteral( "unknown cause" );
}
private:
char *errMsg = nullptr;
};
/**
* sqlite3 handles pointer
*/
QgsSqliteHandle *mHandle = nullptr;
signals:
/**
* This is emitted when this provider is satisfied that all objects
* have had a chance to adjust themselves after they'd been notified that
* the full extent is available.
*
* \note It currently isn't being emitted because we don't have an easy way
* for the overview canvas to only be repainted. In the meantime
* we are satisfied for the overview to reflect the new extent
* when the user adjusts the extent of the main map canvas.
*/
void repaintRequested();
private:
//! Loads fields from input file to member mAttributeFields
void loadFields();
//! For views, try to get primary key from a dedicated meta table
void determineViewPrimaryKey();
//! Check if a table/view has any triggers. Triggers can be used on views to make them editable.
bool hasTriggers();
//! Check if a table has a row id (internal primary key)
bool hasRowid();
//! Convert a QgsField to work with SL
static bool convertField( QgsField &field );
QString geomParam() const;
//! get SpatiaLite version string
QString spatialiteVersion();
/**
* Search all the layers using the given table.
*/
static QList<QgsVectorLayer *> searchLayers( const QList<QgsVectorLayer *> &layers, const QString &connectionInfo, const QString &tableName );
QgsFields mAttributeFields;
//! Flag indicating if the layer data source is a valid SpatiaLite layer
bool mValid = false;
//! Flag indicating if the layer data source is based on a query
bool mIsQuery = false;
//! Flag indicating if the layer data source is based on a plain Table
bool mTableBased = false;
//! Flag indicating if the layer data source is based on a View
bool mViewBased = false;
//! Flag indicating if the layer data source is based on a VirtualShape
bool mVShapeBased = false;
//! Flag indicating if the layer data source has ReadOnly restrictions
bool mReadOnly = false;
//! DB full path
QString mSqlitePath;
//! Name of the table with no schema
QString mTableName;
//! Name of the table or subquery
QString mQuery;
//! Name of the primary key column in the table
QString mPrimaryKey;
//! Flag indicating whether the primary key is auto-generated
bool mPrimaryKeyAutoIncrement = false;
//! List of primary key columns in the table
QgsAttributeList mPrimaryKeyAttrs;
//! Name of the geometry column in the table
QString mGeometryColumn;
//! Map of field index to default value
QMap<int, QVariant> mDefaultValues;
//! Name of the SpatialIndex table
QString mIndexTable;
//! Name of the SpatialIndex geometry column
QString mIndexGeometry;
//! Geometry type
QgsWkbTypes::Type mGeomType = QgsWkbTypes::Unknown;
//! SQLite handle
sqlite3 *mSqliteHandle = nullptr;
//! String used to define a subset of the layer
QString mSubsetString;
//! CoordDimensions of the layer
int nDims;
//! Spatial reference id of the layer
int mSrid = -1;
//! auth id
QString mAuthId;
//! proj4text
QString mProj4text;
//! Rectangle that contains the extent (bounding box) of the layer
QgsRectangle mLayerExtent;
//! Number of features in the layer
long mNumberFeatures = 0;
//! this Geometry is supported by an R*Tree spatial index
bool mSpatialIndexRTree = false;
//! this Geometry is supported by an MBR cache spatial index
bool mSpatialIndexMbrCache = false;
QgsVectorDataProvider::Capabilities mEnabledCapabilities = nullptr;
QgsField field( int index ) const;
//! SpatiaLite version string
QString mSpatialiteVersionInfo;
//! Are mSpatialiteVersionMajor, mSpatialiteVersionMinor valid?
bool mGotSpatialiteVersion = false;
//! SpatiaLite major version
int mSpatialiteVersionMajor = 0;
//! SpatiaLite minor version
int mSpatialiteVersionMinor = 0;
/**
* internal utility functions used to handle common SQLite tasks
*/
//void sqliteOpen();
void closeDb();
bool checkLayerType();
bool getGeometryDetails();
bool getTableGeometryDetails();
bool getViewGeometryDetails();
bool getVShapeGeometryDetails();
bool getQueryGeometryDetails();
bool getSridDetails();
bool getTableSummary();
bool checkLayerTypeAbstractInterface( gaiaVectorLayerPtr lyr );
bool getGeometryDetailsAbstractInterface( gaiaVectorLayerPtr lyr );
bool getTableSummaryAbstractInterface( gaiaVectorLayerPtr lyr );
void loadFieldsAbstractInterface( gaiaVectorLayerPtr lyr );
void getViewSpatialIndexName();
bool prepareStatement( sqlite3_stmt *&stmt,
const QgsAttributeList &fetchAttributes,
bool fetchGeometry,
QString whereClause );
bool getFeature( sqlite3_stmt *stmt, bool fetchGeometry,
QgsFeature &feature,
const QgsAttributeList &fetchAttributes );
void updatePrimaryKeyCapabilities();
int computeSizeFromMultiWKB2D( const unsigned char *p_in, int nDims,
int little_endian,
int endian_arch );
int computeSizeFromMultiWKB3D( const unsigned char *p_in, int nDims,
int little_endian,
int endian_arch );
void convertFromGeosWKB2D( const unsigned char *blob, int blob_size,
unsigned char *wkb, int geom_size,
int nDims, int little_endian, int endian_arch );
void convertFromGeosWKB3D( const unsigned char *blob, int blob_size,
unsigned char *wkb, int geom_size,
int nDims, int little_endian, int endian_arch );
void convertFromGeosWKB( const unsigned char *blob, int blob_size,
unsigned char **wkb, int *geom_size,
int dims );
int computeSizeFromGeosWKB3D( const unsigned char *blob, int size,
QgsWkbTypes::Type type, int nDims, int little_endian,
int endian_arch );
int computeSizeFromGeosWKB2D( const unsigned char *blob, int size,
QgsWkbTypes::Type type, int nDims, int little_endian,
int endian_arch );
void fetchConstraints();
void insertDefaultValue( int fieldIndex, QString defaultVal );
/**
* Handles an error encountered while executing an sql statement.
*/
void handleError( const QString &sql, char *errorMessage, bool rollback = false );
friend class QgsSpatiaLiteFeatureSource;
};
// clazy:excludeall=qstring-allocations
#endif