Skip to content

Commit db18d83

Browse files
committedJan 17, 2014
Oracle provider: added featureSource() support
1 parent 5315cff commit db18d83

File tree

5 files changed

+267
-115
lines changed

5 files changed

+267
-115
lines changed
 

‎src/providers/oracle/qgsoracleconn.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ struct QgsOracleLayerProperty
9696
#endif
9797
};
9898

99-
class QgsOracleConn : public QThread
99+
class QgsOracleConn : public QObject
100100
{
101101
Q_OBJECT;
102102
public:
@@ -125,7 +125,7 @@ class QgsOracleConn : public QThread
125125
/** get primary key candidates (all int4 columns) */
126126
QStringList pkCandidates( QString ownerName, QString viewName );
127127

128-
QString fieldExpression( const QgsField &fld );
128+
static QString fieldExpression( const QgsField &fld );
129129

130130
QString connInfo();
131131

‎src/providers/oracle/qgsoraclefeatureiterator.cpp

Lines changed: 83 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,45 +22,49 @@
2222

2323
#include <QObject>
2424

25-
QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleProvider *p, const QgsFeatureRequest &request )
26-
: QgsAbstractFeatureIterator( request )
27-
, P( p )
25+
QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource* source, bool ownSource, const QgsFeatureRequest &request )
26+
: QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
2827
, mRewind( false )
2928
{
30-
P->mActiveIterators << this;
29+
mConnection = QgsOracleConn::connectDb( mSource->mUri.connectionInfo() );
30+
if ( !mConnection )
31+
{
32+
close();
33+
return;
34+
}
3135

32-
mQry = QSqlQuery( *P->mConnection );
36+
mQry = QSqlQuery( *mConnection );
3337

3438
if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
3539
{
3640
mAttributeList = mRequest.subsetOfAttributes();
3741
if ( mAttributeList.isEmpty() )
38-
mAttributeList = P->attributeIndexes();
42+
mAttributeList = mSource->mFields.allAttributesList();
3943
}
4044
else
41-
mAttributeList = P->attributeIndexes();
45+
mAttributeList = mSource->mFields.allAttributesList();
4246

4347
QString whereClause;
4448

4549
switch ( request.filterType() )
4650
{
4751
case QgsFeatureRequest::FilterRect:
48-
if ( !P->mGeometryColumn.isNull() )
52+
if ( !mSource->mGeometryColumn.isNull() )
4953
{
5054
QgsRectangle rect( mRequest.filterRect() );
5155
QString bbox = QString( "mdsys.sdo_geometry(2003,%1,NULL,"
5256
"mdsys.sdo_elem_info_array(1,1003,3),"
5357
"mdsys.sdo_ordinate_array(%2,%3,%4,%5)"
5458
")" )
55-
.arg( P->mSrid < 1 ? "NULL" : QString::number( P->mSrid ) )
59+
.arg( mSource->mSrid < 1 ? "NULL" : QString::number( mSource->mSrid ) )
5660
.arg( qgsDoubleToString( rect.xMinimum() ) )
5761
.arg( qgsDoubleToString( rect.yMinimum() ) )
5862
.arg( qgsDoubleToString( rect.xMaximum() ) )
5963
.arg( qgsDoubleToString( rect.yMaximum() ) );
6064

61-
if ( !P->mSpatialIndex.isNull() )
65+
if ( !mSource->mSpatialIndex.isNull() )
6266
{
63-
whereClause = QString( "sdo_filter(%1,%2)='TRUE'" ).arg( P->quotedIdentifier( P->mGeometryColumn ) ).arg( bbox );
67+
whereClause = QString( "sdo_filter(%1,%2)='TRUE'" ).arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) ).arg( bbox );
6468
#if 0
6569
if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
6670
{
@@ -74,30 +78,30 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleProvider *p, const
7478
break;
7579

7680
case QgsFeatureRequest::FilterFid:
77-
whereClause = P->whereClause( request.filterFid() );
81+
whereClause = QgsOracleUtils::whereClause( request.filterFid(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
7882
break;
7983

8084
case QgsFeatureRequest::FilterFids:
81-
whereClause = P->whereClause( request.filterFids() );
85+
whereClause = QgsOracleUtils::whereClause( request.filterFids(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
8286
break;
8387

8488
case QgsFeatureRequest::FilterNone:
8589
break;
8690
}
8791

88-
if ( P->mRequestedGeomType != QGis::WKBUnknown && P->mRequestedGeomType != P->mDetectedGeomType )
92+
if ( mSource->mRequestedGeomType != QGis::WKBUnknown && mSource->mRequestedGeomType != mSource->mDetectedGeomType )
8993
{
9094
if ( !whereClause.isEmpty() )
9195
whereClause += " AND ";
9296

93-
whereClause += QgsOracleConn::databaseTypeFilter( "featureRequest", P->mGeometryColumn, P->mRequestedGeomType );
97+
whereClause += QgsOracleConn::databaseTypeFilter( "featureRequest", mSource->mGeometryColumn, mSource->mRequestedGeomType );
9498
}
9599

96-
if ( !P->mSqlWhereClause.isEmpty() )
100+
if ( !mSource->mSqlWhereClause.isEmpty() )
97101
{
98102
if ( !whereClause.isEmpty() )
99103
whereClause += " AND ";
100-
whereClause += "(" + P->mSqlWhereClause + ")";
104+
whereClause += "(" + mSource->mSqlWhereClause + ")";
101105
}
102106

103107
if ( !openQuery( whereClause ) )
@@ -118,7 +122,7 @@ bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature )
118122

119123
for ( ;; )
120124
{
121-
feature.initAttributes( P->fields().count() );
125+
feature.initAttributes( mSource->mFields.count() );
122126
feature.setGeometry( 0 );
123127

124128
if ( mRewind )
@@ -135,15 +139,15 @@ bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature )
135139
int col = 0;
136140

137141
if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0 ||
138-
(( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 && !P->mConnection->hasSpatial() ) )
142+
(( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 && !mConnection->hasSpatial() ) )
139143
{
140144
QByteArray *ba = static_cast<QByteArray*>( mQry.value( col++ ).data() );
141145
unsigned char *copy = new unsigned char[ba->size()];
142146
memcpy( copy, ba->constData(), ba->size() );
143147

144148
feature.setGeometryAndOwnership( copy, ba->size() );
145149

146-
if ( !P->mConnection->hasSpatial() &&
150+
if ( !mConnection->hasSpatial() &&
147151
mRequest.filterType() == QgsFeatureRequest::FilterRect &&
148152
( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 &&
149153
( !feature.geometry() || !feature.geometry()->intersects( mRequest.filterRect() ) ) )
@@ -162,27 +166,27 @@ bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature )
162166

163167
QgsFeatureId fid = 0;
164168

165-
switch ( P->mPrimaryKeyType )
169+
switch ( mSource->mPrimaryKeyType )
166170
{
167-
case QgsOracleProvider::pktInt:
171+
case pktInt:
168172
// get 64bit integer from result
169173
fid = mQry.value( col++ ).toLongLong();
170-
if ( mAttributeList.contains( P->mPrimaryKeyAttrs[0] ) )
171-
feature.setAttribute( P->mPrimaryKeyAttrs[0], fid );
174+
if ( mAttributeList.contains( mSource->mPrimaryKeyAttrs[0] ) )
175+
feature.setAttribute( mSource->mPrimaryKeyAttrs[0], fid );
172176
break;
173177

174-
case QgsOracleProvider::pktRowId:
175-
case QgsOracleProvider::pktFidMap:
178+
case pktRowId:
179+
case pktFidMap:
176180
{
177181
QList<QVariant> primaryKeyVals;
178182

179-
if ( P->mPrimaryKeyType == QgsOracleProvider::pktFidMap )
183+
if ( mSource->mPrimaryKeyType == pktFidMap )
180184
{
181-
foreach ( int idx, P->mPrimaryKeyAttrs )
185+
foreach ( int idx, mSource->mPrimaryKeyAttrs )
182186
{
183-
const QgsField &fld = P->field( idx );
187+
const QgsField &fld = mSource->mFields[idx];
184188

185-
QVariant v = P->convertValue( fld.type(), mQry.value( col ).toString() );
189+
QVariant v = QgsVectorDataProvider::convertValue( fld.type(), mQry.value( col ).toString() );
186190
primaryKeyVals << v;
187191

188192
if ( mAttributeList.contains( idx ) )
@@ -196,11 +200,11 @@ bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature )
196200
primaryKeyVals << mQry.value( col++ );
197201
}
198202

199-
fid = P->lookupFid( QVariant( primaryKeyVals ) );
203+
fid = mSource->mShared->lookupFid( QVariant( primaryKeyVals ) );
200204
}
201205
break;
202206

203-
case QgsOracleProvider::pktUnknown:
207+
case pktUnknown:
204208
Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" );
205209
return false;
206210
}
@@ -211,19 +215,19 @@ bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature )
211215
// iterate attributes
212216
foreach ( int idx, mAttributeList )
213217
{
214-
if ( P->mPrimaryKeyAttrs.contains( idx ) )
218+
if ( mSource->mPrimaryKeyAttrs.contains( idx ) )
215219
continue;
216220

217-
const QgsField &fld = P->field( idx );
221+
const QgsField &fld = mSource->mFields[idx];
218222

219-
QVariant v = P->convertValue( fld.type(), mQry.value( col ).toString() );
223+
QVariant v = QgsVectorDataProvider::convertValue( fld.type(), mQry.value( col ).toString() );
220224
feature.setAttribute( idx, v );
221225

222226
col++;
223227
}
224228

225229
feature.setValid( true );
226-
feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups
230+
feature.setFields( &mSource->mFields ); // allow name-based attribute lookups
227231

228232
return true;
229233
}
@@ -246,14 +250,18 @@ bool QgsOracleFeatureIterator::close()
246250

247251
mQry.finish();
248252

249-
P->mActiveIterators.remove( this );
253+
if ( mConnection )
254+
mConnection->disconnect();
255+
mConnection = 0;
256+
257+
iteratorClosed();
250258

251259
return true;
252260
}
253261

254262
bool QgsOracleFeatureIterator::openQuery( QString whereClause )
255263
{
256-
if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0 && P->mGeometryColumn.isNull() )
264+
if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0 && mSource->mGeometryColumn.isNull() )
257265
{
258266
return false;
259267
}
@@ -264,51 +272,51 @@ bool QgsOracleFeatureIterator::openQuery( QString whereClause )
264272

265273
if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0 )
266274
{
267-
query += P->quotedIdentifier( P->mGeometryColumn );
275+
query += QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn );
268276
delim = ",";
269277
}
270278

271-
switch ( P->mPrimaryKeyType )
279+
switch ( mSource->mPrimaryKeyType )
272280
{
273-
case QgsOracleProvider::pktRowId:
274-
query += delim + P->quotedIdentifier( "ROWID" );
281+
case pktRowId:
282+
query += delim + QgsOracleProvider::quotedIdentifier( "ROWID" );
275283
delim = ",";
276284
break;
277285

278-
case QgsOracleProvider::pktInt:
279-
query += delim + P->quotedIdentifier( P->field( P->mPrimaryKeyAttrs[0] ).name() );
286+
case pktInt:
287+
query += delim + QgsOracleProvider::quotedIdentifier( mSource->mFields[ mSource->mPrimaryKeyAttrs[0] ].name() );
280288
delim = ",";
281289
break;
282290

283-
case QgsOracleProvider::pktFidMap:
284-
foreach ( int idx, P->mPrimaryKeyAttrs )
291+
case pktFidMap:
292+
foreach ( int idx, mSource->mPrimaryKeyAttrs )
285293
{
286-
query += delim + P->mConnection->fieldExpression( P->field( idx ) );
294+
query += delim + mConnection->fieldExpression( mSource->mFields[idx] );
287295
delim = ",";
288296
}
289297
break;
290298

291-
case QgsOracleProvider::pktUnknown:
299+
case pktUnknown:
292300
QgsDebugMsg( "Cannot query without primary key." );
293301
return false;
294302
break;
295303
}
296304

297305
foreach ( int idx, mAttributeList )
298306
{
299-
if ( P->mPrimaryKeyAttrs.contains( idx ) )
307+
if ( mSource->mPrimaryKeyAttrs.contains( idx ) )
300308
continue;
301309

302-
query += delim + P->mConnection->fieldExpression( P->field( idx ) );
310+
query += delim + mConnection->fieldExpression( mSource->mFields[idx] );
303311
}
304312

305-
query += QString( " FROM %1 \"featureRequest\"" ).arg( P->mQuery );
313+
query += QString( " FROM %1 \"featureRequest\"" ).arg( mSource->mQuery );
306314

307315
if ( !whereClause.isEmpty() )
308316
query += QString( " WHERE %1" ).arg( whereClause );
309317

310318
QgsDebugMsg( QString( "Fetch features: %1" ).arg( query ) );
311-
if ( !P->exec( mQry, query ) )
319+
if ( !QgsOracleProvider::exec( mQry, query ) )
312320
{
313321
QgsMessageLog::logMessage( QObject::tr( "Fetching features failed.\nSQL:%1\nError: %2" )
314322
.arg( mQry.lastQuery() )
@@ -324,3 +332,26 @@ bool QgsOracleFeatureIterator::openQuery( QString whereClause )
324332

325333
return true;
326334
}
335+
336+
// -----------
337+
338+
QgsOracleFeatureSource::QgsOracleFeatureSource( const QgsOracleProvider* p )
339+
: mUri( p->mUri )
340+
, mFields( p->mAttributeFields )
341+
, mGeometryColumn( p->mGeometryColumn )
342+
, mSrid( p->mSrid )
343+
, mSpatialIndex( p->mSpatialIndex )
344+
, mDetectedGeomType( p->mDetectedGeomType )
345+
, mRequestedGeomType( p->mRequestedGeomType )
346+
, mSqlWhereClause( p->mSqlWhereClause )
347+
, mPrimaryKeyType( p->mPrimaryKeyType )
348+
, mPrimaryKeyAttrs( p->mPrimaryKeyAttrs )
349+
, mQuery( p->mQuery )
350+
, mShared( p->mShared )
351+
{
352+
}
353+
354+
QgsFeatureIterator QgsOracleFeatureSource::getFeatures( const QgsFeatureRequest& request )
355+
{
356+
return QgsFeatureIterator( new QgsOracleFeatureIterator( this, false, request ) );
357+
}

‎src/providers/oracle/qgsoraclefeatureiterator.h

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,43 @@
2222

2323
#include <QSqlQuery>
2424

25+
#include "qgsoracleprovider.h"
2526

27+
class QgsOracleConn;
2628
class QgsOracleProvider;
2729

28-
class QgsOracleFeatureIterator : public QgsAbstractFeatureIterator
30+
31+
class QgsOracleFeatureSource : public QgsAbstractFeatureSource
32+
{
33+
public:
34+
QgsOracleFeatureSource( const QgsOracleProvider* p );
35+
36+
virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest& request );
37+
38+
protected:
39+
QgsDataSourceURI mUri;
40+
QgsFields mFields;
41+
42+
QString mGeometryColumn; //! name of the geometry column
43+
int mSrid; //! srid of column
44+
QString mSpatialIndex; //! name of spatial index of geometry column
45+
QGis::WkbType mDetectedGeomType; //! geometry type detected in the database
46+
QGis::WkbType mRequestedGeomType; //! geometry type requested in the uri
47+
QString mSqlWhereClause;
48+
QgsOraclePrimaryKeyType mPrimaryKeyType;
49+
QList<int> mPrimaryKeyAttrs;
50+
QString mQuery;
51+
52+
QSharedPointer<QgsOracleSharedData> mShared;
53+
54+
friend class QgsOracleFeatureIterator;
55+
};
56+
57+
58+
class QgsOracleFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsOracleFeatureSource>
2959
{
3060
public:
31-
QgsOracleFeatureIterator( QgsOracleProvider *p, const QgsFeatureRequest &request );
61+
QgsOracleFeatureIterator( QgsOracleFeatureSource* source, bool ownSource, const QgsFeatureRequest &request );
3262

3363
~QgsOracleFeatureIterator();
3464

@@ -42,10 +72,9 @@ class QgsOracleFeatureIterator : public QgsAbstractFeatureIterator
4272
//! fetch next feature, return true on success
4373
virtual bool fetchFeature( QgsFeature& feature );
4474

45-
QgsOracleProvider *P;
46-
4775
bool openQuery( QString whereClause );
4876

77+
QgsOracleConn *mConnection;
4978
QSqlQuery mQry;
5079
bool mRewind;
5180
QgsAttributeList mAttributeList;

0 commit comments

Comments
 (0)
Please sign in to comment.