/
qgsoracleprovider.h
397 lines (310 loc) · 12.6 KB
/
qgsoracleprovider.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
/***************************************************************************
qgsoracleprovider.h - Data provider for oracle layers
-------------------
begin : August 2012
copyright : (C) 2012 by Juergen E. Fischer
email : jef at norbit dot de
***************************************************************************/
/***************************************************************************
* *
* 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 QGSORACLEPROVIDER_H
#define QGSORACLEPROVIDER_H
#include "qgsvectordataprovider.h"
#include "qgsrectangle.h"
#include "qgsvectorlayerimport.h"
#include "qgsoracletablemodel.h"
#include "qgsdatasourceuri.h"
#include <QVector>
#include <QQueue>
#include <QSqlQuery>
#include <QSqlError>
class QgsFeature;
class QgsField;
class QgsGeometry;
class QgsOracleFeatureIterator;
/**
\class QgsOracleProvider
\brief Data provider for oracle layers.
This provider implements the
interface defined in the QgsDataProvider class to provide access to spatial
data residing in a oracle enabled database.
*/
class QgsOracleProvider : public QgsVectorDataProvider
{
Q_OBJECT
public:
/** Import a vector layer into the database */
static QgsVectorLayerImport::ImportError createEmptyLayer(
const QString& uri,
const QgsFields &fields,
QGis::WkbType wkbType,
const QgsCoordinateReferenceSystem *srs,
bool overwrite,
QMap<int, int> *oldToNewAttrIdxMap,
QString *errorMessage = 0,
const QMap<QString, QVariant> *options = 0
);
/**
* Constructor for the provider. The uri must be in the following format:
* host=localhost user=gsherman dbname=test password=xxx table=test.alaska (the_geom)
* @param uri String containing the required parameters to connect to the database
* and query the table.
*/
QgsOracleProvider( QString const &uri = "" );
//! Destructor
virtual ~QgsOracleProvider();
/**
* Returns the permanent storage type for this layer as a friendly name.
*/
virtual QString storageType() const;
/*! Get the QgsCoordinateReferenceSystem for this layer
* @note Must be reimplemented by each provider.
* If the provider isn't capable of returning
* its projection an empty srs will be returned
*/
virtual QgsCoordinateReferenceSystem crs();
/** Get the feature type. This corresponds to
* WKBPoint,
* WKBLineString,
* WKBPolygon,
* WKBMultiPoint,
* WKBMultiLineString or
* WKBMultiPolygon
* as defined in qgis.h
*/
QGis::WkbType geometryType() const;
/** return the number of layers for the current data source
* @note Should this be subLayerCount() instead?
*/
size_t layerCount() const;
/**
* Get the number of features in the layer
*/
long featureCount() const;
/**
* Get the number of fields in the layer
*/
uint fieldCount() const;
/**
* Return a string representation of the endian-ness for the layer
*/
QString endianString();
/**
* Changes the stored extent for this layer to the supplied extent.
* For example, this is called when the extent worker thread has a result.
*/
void setExtent( QgsRectangle& newExtent );
/** Return the extent for this data layer
*/
virtual QgsRectangle extent();
/** Update the extent
*/
virtual void updateExtents();
/** Determine the fields making up the primary key
*/
bool determinePrimaryKey();
/**
* Get the field information for the layer
* @return vector of QgsField objects
*/
const QgsFields &fields() const;
/**
* Return a short comment for the data that this provider is
* providing access to (e.g. the comment for oracle table).
*/
QString dataComment() const;
/** Reset the layer
*/
void rewind();
/** Returns the minimum value of an attribute
* @param index the index of the attribute */
QVariant minimumValue( int index );
/** Returns the maximum value of an attribute
* @param index the index of the attribute */
QVariant maximumValue( int index );
/** Return the unique values of an attribute
* @param index the index of the attribute
* @param values reference to the list of unique values */
virtual void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 );
/**Returns true if layer is valid
*/
bool isValid();
QgsAttributeList pkAttributeIndexes() { return mPrimaryKeyAttrs; }
/**Returns the default value for field specified by @c fieldName */
QVariant defaultValue( QString fieldName, QString tableName = QString::null, QString schemaName = QString::null );
/**Returns the default value for field specified by @c fieldId */
QVariant defaultValue( int fieldId );
/**Adds a list of features
@return true in case of success and false in case of failure*/
bool addFeatures( QgsFeatureList & flist );
/**Deletes a list of features
@param id list of feature ids
@return true in case of success and false in case of failure*/
bool deleteFeatures( const QgsFeatureIds & id );
/**Adds new attributes
@param name map with attribute name as key and type as value
@return true in case of success and false in case of failure*/
bool addAttributes( const QList<QgsField> &attributes );
/**Deletes existing attributes
@param names of the attributes to delete
@return true in case of success and false in case of failure*/
bool deleteAttributes( const QgsAttributeIds & name );
/**Changes attribute values of existing features
@param attr_map a map containing the new attributes. The integer is the feature id,
the first QString is the attribute name and the second one is the new attribute value
@return true in case of success and false in case of failure*/
bool changeAttributeValues( const QgsChangedAttributesMap & attr_map );
/**
Changes geometries of existing features
@param geometry_map A QMap containing the feature IDs to change the geometries of.
the second map parameter being the new geometries themselves
@return true in case of success and false in case of failure
*/
bool changeGeometryValues( QgsGeometryMap & geometry_map );
/**Tries to create an spatial index file for faster access if only a subset of the features is required
@return true in case of success*/
bool createSpatialIndex();
//! Get the table name associated with this provider instance
QString getTableName();
/** Accessor for sql where clause used to limit dataset */
QString subsetString();
/** mutator for sql where clause used to limit dataset size */
bool setSubsetString( QString theSQL, bool updateFeatureCount = true );
virtual bool supportsSubsetString() { return true; }
/**Returns a bitmask containing the supported capabilities*/
int capabilities() const;
/** return a provider name
Essentially just returns the provider key. Should be used to build file
dialogs so that providers can be shown with their supported types. Thus
if more than one provider supports a given format, the user is able to
select a specific provider to open that file.
@note
Instead of being pure virtual, might be better to generalize this
behavior and presume that none of the sub-classes are going to do
anything strange with regards to their name or description?
*/
QString name() const;
/** return description
Return a terse string describing what the provider is.
@note
Instead of being pure virtual, might be better to generalize this
behavior and presume that none of the sub-classes are going to do
anything strange with regards to their name or description?
*/
QString description() const;
/**
* Query the provider for features specified in request.
*/
virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest& request = QgsFeatureRequest() );
static bool exec( QSqlQuery &qry, QString sql );
private:
QString whereClause( QgsFeatureId featureId ) const;
QString pkParamWhereClause() const;
QString paramValue( QString fieldvalue, const QString &defaultValue ) const;
void appendGeomParam( QgsGeometry *geom, QSqlQuery &qry ) const;
void appendPkParams( QgsFeatureId fid, QSqlQuery &qry ) const;
bool hasSufficientPermsAndCapabilities();
const QgsField &field( int index ) const;
/** Load the field list
*/
bool loadFields();
/** convert a QgsField to work with Oracle */
static bool convertField( QgsField &field );
QgsFields mAttributeFields; //! List of fields
QVariantList mDefaultValues; //! List of default values
QString mDataComment;
//! Data source URI struct for this layer
QgsDataSourceURI mUri;
/**
* Flag indicating if the layer data source is a valid oracle layer
*/
bool mValid;
/**
* provider references query (instead of a table)
*/
bool mIsQuery;
/**
* Name of the table with no schema
*/
QString mTableName;
/**
* Name of the table or subquery
*/
QString mQuery;
/**
* Owner of the table
*/
QString mOwnerName;
/**
* SQL statement used to limit the features retrieved
*/
QString mSqlWhereClause;
/**
* Data type for the primary key
*/
enum { pktUnknown, pktInt, pktRowId, pktFidMap } mPrimaryKeyType;
/**
* List of primary key attributes for fetching features.
*/
QList<int> mPrimaryKeyAttrs;
QString mPrimaryKeyDefault;
QString mGeometryColumn; //! name of the geometry column
QgsRectangle mLayerExtent; //! Rectangle that contains the extent (bounding box) of the layer
mutable long mFeaturesCounted; //! Number of features in the layer
int mSrid; //! srid of column
int mEnabledCapabilities; //! capabilities of layer
QGis::WkbType mDetectedGeomType; //! geometry type detected in the database
QGis::WkbType mRequestedGeomType; //! geometry type requested in the uri
bool getGeometryDetails();
/* Use estimated metadata. Uses fast table counts, geometry type and extent determination */
bool mUseEstimatedMetadata;
struct OracleFieldNotFound {}; //! Exception to throw
struct OracleException
{
OracleException( QString msg, const QSqlQuery &q )
: mWhat( tr( "Oracle error: %1\nSQL: %2\nError: %3" )
.arg( msg )
.arg( q.lastError().text() )
.arg( q.lastQuery() )
)
{}
OracleException( QString msg, const QSqlDatabase &q )
: mWhat( tr( "Oracle error: %1\nError: %2" )
.arg( msg )
.arg( q.lastError().text() )
)
{}
OracleException( const OracleException &e )
: mWhat( e.errorMessage() )
{}
~OracleException()
{}
QString errorMessage() const
{
return mWhat;
}
private:
QString mWhat;
};
// A function that determines if the given schema.table.column
// contains unqiue entries
bool uniqueData( QString query, QString colName );
void disconnectDb();
static QString quotedIdentifier( QString ident ) { return QgsOracleConn::quotedIdentifier( ident ); }
static QString quotedValue( QVariant value ) { return QgsOracleConn::quotedValue( value ); }
QgsFeatureId lookupFid( const QVariant &v ); //! lookup existing mapping or add a new one
QMap<QVariant, QgsFeatureId> mKeyToFid; //! map key values to feature id
QMap<QgsFeatureId, QVariant> mFidToKey; //! map feature back to fea
QgsFeatureId mFidCounter; //! next feature id if map is used
QgsOracleConn *mConnection;
QString mSpatialIndex; //! name of spatial index of geometry column
bool mHasSpatial; //! Oracle Spatial is installed
friend class QgsOracleFeatureIterator;
};
#endif