23
23
#include < QTextStream>
24
24
25
25
26
- QgsMssqlFeatureIterator::QgsMssqlFeatureIterator ( QgsMssqlProvider* provider , const QgsFeatureRequest& request )
27
- : QgsAbstractFeatureIterator( request ), mProvider( provider )
26
+ QgsMssqlFeatureIterator::QgsMssqlFeatureIterator ( QgsMssqlFeatureSource* source, bool ownSource , const QgsFeatureRequest& request )
27
+ : QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
28
28
{
29
- mIsOpen = false ;
30
- BuildStatement ( request );
31
-
29
+ mClosed = false ;
32
30
mQuery = NULL ;
33
31
34
- if ( mProvider ->mQuery .isActive () )
35
- {
36
- mUseProviderQuery = false ;
37
- // create a separate database connection if the default query is active
38
- QgsDebugMsg ( " Creating a separate database connection" );
39
- QString id;
40
- // QString::sprintf adds 0x prefix
41
- id.sprintf ( " %p" , this );
42
- mDatabase = mProvider ->mDatabase .cloneDatabase ( mProvider ->mDatabase , id );
43
- if ( !mDatabase .open () )
44
- {
45
- QgsDebugMsg ( " Failed to open database" );
46
- QString msg = mDatabase .lastError ().text ();
47
- QgsDebugMsg ( msg );
48
- return ;
49
- }
50
- // create sql query
51
- mQuery = new QSqlQuery ( mDatabase );
52
- }
53
- else
32
+ mParser .IsGeography = mSource ->mIsGeography ;
33
+
34
+ BuildStatement ( request );
35
+
36
+ // connect to the database
37
+ mDatabase = GetDatabase (mSource ->mDriver , mSource ->mHost , mSource ->mDatabaseName , mSource ->mUserName , mSource ->mPassword );
38
+
39
+ if ( !mDatabase .open () )
54
40
{
55
- mUseProviderQuery = true ;
56
- mQuery = &mProvider ->mQuery ;
41
+ QgsDebugMsg ( " Failed to open database" );
42
+ QString msg = mDatabase .lastError ().text ();
43
+ QgsDebugMsg ( msg );
44
+ return ;
57
45
}
46
+
47
+ // create sql query
48
+ mQuery = new QSqlQuery ( mDatabase );
49
+
58
50
// start selection
59
51
rewind ();
60
52
}
61
53
62
54
63
55
QgsMssqlFeatureIterator::~QgsMssqlFeatureIterator ()
64
56
{
65
- if ( ! mUseProviderQuery )
66
- {
67
- if ( mQuery )
57
+ close ();
58
+
59
+ if ( mQuery )
68
60
delete mQuery ;
61
+
62
+ if (mDatabase .isOpen ())
69
63
mDatabase .close ();
70
- }
71
- else if ( mIsOpen )
72
- close ();
73
64
}
74
65
75
66
void QgsMssqlFeatureIterator::BuildStatement ( const QgsFeatureRequest& request )
@@ -87,9 +78,9 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest& request )
87
78
{
88
79
if ( fieldCount != 0 )
89
80
mStatement += " ," ;
90
- mStatement += " [" + mProvider -> mAttributeFields [*it].name () + " ]" ;
81
+ mStatement += " [" + mSource -> mFields [*it].name () + " ]" ;
91
82
92
- if ( !mProvider ->mFidColName .isEmpty () && mProvider ->mFidColName == mProvider -> mAttributeFields [*it].name () )
83
+ if ( !mSource ->mFidColName .isEmpty () && mSource ->mFidColName == mSource -> mFields [*it].name () )
93
84
mFidCol = fieldCount;
94
85
95
86
++fieldCount;
@@ -99,43 +90,43 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest& request )
99
90
else
100
91
{
101
92
// get all attributes
102
- for ( int i = 0 ; i < mProvider -> mAttributeFields .count (); i++ )
93
+ for ( int i = 0 ; i < mSource -> mFields .count (); i++ )
103
94
{
104
95
if ( fieldCount != 0 )
105
96
mStatement += " ," ;
106
- mStatement += " [" + mProvider -> mAttributeFields [i].name () + " ]" ;
97
+ mStatement += " [" + mSource -> mFields [i].name () + " ]" ;
107
98
108
- if ( !mProvider ->mFidColName .isEmpty () && mProvider ->mFidColName == mProvider -> mAttributeFields [i].name () )
99
+ if ( !mSource ->mFidColName .isEmpty () && mSource ->mFidColName == mSource -> mFields [i].name () )
109
100
mFidCol = fieldCount;
110
101
111
102
++fieldCount;
112
103
mAttributesToFetch .append ( i );
113
104
}
114
105
}
115
106
// get fid col if not yet required
116
- if ( mFidCol == -1 && !mProvider ->mFidColName .isEmpty () )
107
+ if ( mFidCol == -1 && !mSource ->mFidColName .isEmpty () )
117
108
{
118
109
if ( fieldCount != 0 )
119
110
mStatement += " ," ;
120
- mStatement += " [" + mProvider ->mFidColName + " ]" ;
111
+ mStatement += " [" + mSource ->mFidColName + " ]" ;
121
112
mFidCol = fieldCount;
122
113
++fieldCount;
123
114
}
124
115
// get geometry col
125
- if ( !( request.flags () & QgsFeatureRequest::NoGeometry ) && !mProvider ->mGeometryColName .isEmpty () )
116
+ if ( !( request.flags () & QgsFeatureRequest::NoGeometry ) && !mSource ->mGeometryColName .isEmpty () )
126
117
{
127
118
if ( fieldCount != 0 )
128
119
mStatement += " ," ;
129
- mStatement += " [" + mProvider ->mGeometryColName + " ]" ;
120
+ mStatement += " [" + mSource ->mGeometryColName + " ]" ;
130
121
mGeometryCol = fieldCount;
131
122
++fieldCount;
132
123
}
133
124
134
125
mStatement += " from " ;
135
- if ( !mProvider ->mSchemaName .isEmpty () )
136
- mStatement += " [" + mProvider ->mSchemaName + " ]." ;
126
+ if ( !mSource ->mSchemaName .isEmpty () )
127
+ mStatement += " [" + mSource ->mSchemaName + " ]." ;
137
128
138
- mStatement += " [" + mProvider ->mTableName + " ]" ;
129
+ mStatement += " [" + mSource ->mTableName + " ]" ;
139
130
140
131
bool filterAdded = false ;
141
132
// set spatial filter
@@ -154,27 +145,27 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest& request )
154
145
<< request.filterRect ().xMinimum () << " " << request.filterRect ().yMinimum ();
155
146
156
147
mStatement += QString ( " where [%1].STIntersects([%2]::STGeomFromText('POLYGON((%3))',%4)) = 1" ).arg (
157
- mProvider ->mGeometryColName , mProvider ->mGeometryColType , r, QString::number ( mProvider ->mSRId ) );
148
+ mSource ->mGeometryColName , mSource ->mGeometryColType , r, QString::number ( mSource ->mSRId ) );
158
149
filterAdded = true ;
159
150
}
160
151
161
152
// set fid filter
162
- if (( request.filterType () & QgsFeatureRequest::FilterFid ) && !mProvider ->mFidColName .isEmpty () )
153
+ if (( request.filterType () & QgsFeatureRequest::FilterFid ) && !mSource ->mFidColName .isEmpty () )
163
154
{
164
155
// set attribute filter
165
156
if ( !filterAdded )
166
- mStatement += QString ( " where [%1] = %2" ).arg ( mProvider ->mFidColName , QString::number ( request.filterFid () ) );
157
+ mStatement += QString ( " where [%1] = %2" ).arg ( mSource ->mFidColName , QString::number ( request.filterFid () ) );
167
158
else
168
- mStatement += QString ( " and [%1] = %2" ).arg ( mProvider ->mFidColName , QString::number ( request.filterFid () ) );
159
+ mStatement += QString ( " and [%1] = %2" ).arg ( mSource ->mFidColName , QString::number ( request.filterFid () ) );
169
160
filterAdded = true ;
170
161
}
171
162
172
- if ( !mProvider ->mSqlWhereClause .isEmpty () )
163
+ if ( !mSource ->mSqlWhereClause .isEmpty () )
173
164
{
174
165
if ( !filterAdded )
175
- mStatement += " where (" + mProvider ->mSqlWhereClause + " )" ;
166
+ mStatement += " where (" + mSource ->mSqlWhereClause + " )" ;
176
167
else
177
- mStatement += " and (" + mProvider ->mSqlWhereClause + " )" ;
168
+ mStatement += " and (" + mSource ->mSqlWhereClause + " )" ;
178
169
}
179
170
180
171
if ( fieldCount == 0 )
@@ -200,8 +191,8 @@ bool QgsMssqlFeatureIterator::fetchFeature( QgsFeature& feature )
200
191
201
192
if ( mQuery ->next () )
202
193
{
203
- feature.initAttributes ( mProvider -> mAttributeFields .count () );
204
- feature.setFields ( &mProvider -> mAttributeFields ); // allow name-based attribute lookups
194
+ feature.initAttributes ( mSource -> mFields .count () );
195
+ feature.setFields ( &mSource -> mFields ); // allow name-based attribute lookups
205
196
206
197
for ( int i = 0 ; i < mAttributesToFetch .count (); i++ )
207
198
{
@@ -217,10 +208,10 @@ bool QgsMssqlFeatureIterator::fetchFeature( QgsFeature& feature )
217
208
if ( mGeometryCol >= 0 )
218
209
{
219
210
QByteArray ar = mQuery ->value ( mGeometryCol ).toByteArray ();
220
- unsigned char * wkb = mProvider -> parser .ParseSqlGeometry (( unsigned char * )ar.data (), ar.size () );
211
+ unsigned char * wkb = mParser .ParseSqlGeometry (( unsigned char * )ar.data (), ar.size () );
221
212
if ( wkb )
222
213
{
223
- feature.setGeometryAndOwnership ( wkb, mProvider -> parser .GetWkbLen () );
214
+ feature.setGeometryAndOwnership ( wkb, mParser .GetWkbLen () );
224
215
}
225
216
}
226
217
@@ -249,27 +240,128 @@ bool QgsMssqlFeatureIterator::rewind()
249
240
QString msg = mQuery ->lastError ().text ();
250
241
QgsDebugMsg ( msg );
251
242
}
252
- else
253
- mIsOpen = true ;
254
243
255
244
return true ;
256
245
}
257
246
258
247
bool QgsMssqlFeatureIterator::close ()
259
248
{
260
- mIsOpen = false ;
261
- if ( !mQuery )
249
+ if ( mClosed )
262
250
return false ;
263
251
264
- if ( ! mQuery -> isActive () )
252
+ if ( mQuery )
265
253
{
266
- QgsDebugMsg ( " QgsMssqlFeatureIterator::close on inactive query" );
267
- return false ;
254
+ if ( !mQuery ->isActive () )
255
+ {
256
+ QgsDebugMsg ( " QgsMssqlFeatureIterator::close on inactive query" );
257
+ return false ;
258
+ }
259
+
260
+ mQuery ->finish ();
268
261
}
269
262
270
- mQuery ->finish ();
263
+ iteratorClosed ();
264
+
265
+ mClosed = true ;
271
266
return true ;
272
267
}
273
268
269
+ QSqlDatabase QgsMssqlFeatureIterator::GetDatabase (QString driver, QString host, QString database, QString username, QString password)
270
+ {
271
+ QSqlDatabase db;
272
+ QString connectionName;
273
+
274
+ // create a separate database connection for each feature source
275
+ QgsDebugMsg ( " Creating a separate database connection" );
276
+ QString id;
277
+
278
+ // QString::sprintf adds 0x prefix
279
+ id.sprintf ( " %p" , this );
280
+
281
+ if ( driver.isEmpty () )
282
+ {
283
+ if ( host.isEmpty () )
284
+ {
285
+ QgsDebugMsg ( " QgsMssqlProvider host name not specified" );
286
+ return db;
287
+ }
288
+
289
+ if ( database.isEmpty () )
290
+ {
291
+ QgsDebugMsg ( " QgsMssqlProvider database name not specified" );
292
+ return db;
293
+ }
294
+ connectionName = host + " ." + database + " ." + id;
295
+ }
296
+ else
297
+ connectionName = driver;
298
+
299
+ if ( !QSqlDatabase::contains ( connectionName ) )
300
+ db = QSqlDatabase::addDatabase ( " QODBC" , connectionName );
301
+ else
302
+ db = QSqlDatabase::database ( connectionName );
303
+
304
+ db.setHostName ( host );
305
+ QString connectionString = " " ;
306
+ if ( !driver.isEmpty () )
307
+ {
308
+ // driver was specified explicitly
309
+ connectionString = driver;
310
+ }
311
+ else
312
+ {
313
+ #ifdef WIN32
314
+ connectionString = " driver={SQL Server}" ;
315
+ #else
316
+ connectionString = " driver={FreeTDS};port=1433" ;
317
+ #endif
318
+ }
319
+
320
+ if ( !host.isEmpty () )
321
+ connectionString += " ;server=" + host;
322
+
323
+ if ( !database.isEmpty () )
324
+ connectionString += " ;database=" + database;
325
+
326
+ if ( password.isEmpty () )
327
+ connectionString += " ;trusted_connection=yes" ;
328
+ else
329
+ connectionString += " ;uid=" + username + " ;pwd=" + password;
330
+
331
+ if ( !username.isEmpty () )
332
+ db.setUserName ( username );
333
+
334
+ if ( !password.isEmpty () )
335
+ db.setPassword ( password );
336
+
337
+ db.setDatabaseName ( connectionString );
338
+ return db;
339
+ }
340
+
274
341
// /////////////
275
342
343
+ QgsMssqlFeatureSource::QgsMssqlFeatureSource ( const QgsMssqlProvider* p )
344
+ : mFields( p->mAttributeFields )
345
+ , mFidColName( p->mFidColName )
346
+ , mGeometryColName( p->mGeometryColName )
347
+ , mGeometryColType( p->mGeometryColType )
348
+ , mUserName( p->mUserName )
349
+ , mService( p->mService )
350
+ , mDatabaseName( p->mDatabaseName )
351
+ , mHost( p->mHost )
352
+ , mSchemaName( p->mSchemaName )
353
+ , mTableName( p->mTableName )
354
+ , mSqlWhereClause( p->mSqlWhereClause )
355
+ {
356
+ mSRId = p->mSRId ;
357
+ mIsGeography = p->mParser .IsGeography ;
358
+ }
359
+
360
+ QgsMssqlFeatureSource::~QgsMssqlFeatureSource ()
361
+ {
362
+ }
363
+
364
+ QgsFeatureIterator QgsMssqlFeatureSource::getFeatures ( const QgsFeatureRequest& request )
365
+ {
366
+ return QgsFeatureIterator ( new QgsMssqlFeatureIterator ( this , false , request ) );
367
+ }
0 commit comments