Skip to content

Commit

Permalink
[mssql] Fix iteration failure from background threads
Browse files Browse the repository at this point in the history
We need to defer the database retrieval until iteration begins,
because otherwise we are creating the database in the main thread
and then using it in another thread (blocked in Qt 5.11, dangerous
in Qt < 5.11).
  • Loading branch information
nyalldawson committed Oct 2, 2018
1 parent b7333c0 commit dcca55c
Showing 1 changed file with 26 additions and 15 deletions.
41 changes: 26 additions & 15 deletions src/providers/mssql/qgsmssqlfeatureiterator.cpp
Expand Up @@ -51,21 +51,11 @@ QgsMssqlFeatureIterator::QgsMssqlFeatureIterator( QgsMssqlFeatureSource *source,

BuildStatement( request );

// connect to the database
mDatabase = QgsMssqlProvider::GetDatabase( mSource->mService, mSource->mHost, mSource->mDatabaseName, mSource->mUserName, mSource->mPassword );

if ( !mDatabase.open() )
{
QgsDebugMsg( "Failed to open database" );
QgsDebugMsg( mDatabase.lastError().text() );
return;
}

// create sql query
mQuery.reset( new QSqlQuery( mDatabase ) );

// start selection
rewind();
// WARNING - we can't obtain the database connection now, as this method should be
// run from the main thread, yet iteration can be done in a different thread.
// This would result in failure, because QSqlDatabase instances cannot be used
// from a different thread where they were created. Instead, we defer creation
// of the database until the first feature is fetched.
}


Expand Down Expand Up @@ -294,6 +284,27 @@ bool QgsMssqlFeatureIterator::fetchFeature( QgsFeature &feature )
{
feature.setValid( false );

if ( !mDatabase.isValid() )
{
// No existing connection, so set it up now. It's safe to do here as we're now in
// the thread were iteration is actually occurring.
mDatabase = QgsMssqlProvider::GetDatabase( mSource->mService, mSource->mHost, mSource->mDatabaseName, mSource->mUserName, mSource->mPassword );

if ( !mDatabase.open() )
{
QgsDebugMsg( "Failed to open database" );
QgsDebugMsg( mDatabase.lastError().text() );
return false;
}

// create sql query
mQuery.reset( new QSqlQuery( mDatabase ) );

// start selection
if ( !rewind() )
return false;
}

if ( !mQuery )
return false;

Expand Down

0 comments on commit dcca55c

Please sign in to comment.