Skip to content

Commit

Permalink
Speed up spatialite provider
Browse files Browse the repository at this point in the history
No need to iterate over all the features in the datasource only to find
out that there is no feature which is not in an empty list of feature
ids.
  • Loading branch information
m-kuhn committed Oct 24, 2017
1 parent 269f751 commit 86b28ff
Showing 1 changed file with 66 additions and 60 deletions.
126 changes: 66 additions & 60 deletions src/providers/spatialite/qgsspatialitefeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
catch ( QgsCsException & )
{
// can't reproject mFilterRect
mClosed = true;
close();
return;
}

Expand Down Expand Up @@ -90,10 +90,13 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
}
else if ( request.filterType() == QgsFeatureRequest::FilterFids )
{
whereClause = whereClauseFids();
if ( ! whereClause.isEmpty() )
if ( request.filterFids().isEmpty() )
{
whereClauses.append( whereClause );
close();
}
else
{
whereClauses.append( whereClauseFids() );
}
}
//IMPORTANT - this MUST be the last clause added!
Expand Down Expand Up @@ -144,77 +147,80 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
}
}

whereClause = whereClauses.join( QStringLiteral( " AND " ) );
if ( !mClosed )
{
whereClause = whereClauses.join( QStringLiteral( " AND " ) );

// Setup the order by
QStringList orderByParts;
// Setup the order by
QStringList orderByParts;

mOrderByCompiled = true;
mOrderByCompiled = true;

if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
{
Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, request.orderBy() )
if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
{
QgsSQLiteExpressionCompiler compiler = QgsSQLiteExpressionCompiler( source->mFields );
QgsExpression expression = clause.expression();
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, request.orderBy() )
{
QString part;
part = compiler.result();
QgsSQLiteExpressionCompiler compiler = QgsSQLiteExpressionCompiler( source->mFields );
QgsExpression expression = clause.expression();
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
{
QString part;
part = compiler.result();

if ( clause.nullsFirst() )
orderByParts << QStringLiteral( "%1 IS NOT NULL" ).arg( part );
else
orderByParts << QStringLiteral( "%1 IS NULL" ).arg( part );
if ( clause.nullsFirst() )
orderByParts << QStringLiteral( "%1 IS NOT NULL" ).arg( part );
else
orderByParts << QStringLiteral( "%1 IS NULL" ).arg( part );

part += clause.ascending() ? " COLLATE NOCASE ASC" : " COLLATE NOCASE DESC";
orderByParts << part;
}
else
{
// Bail out on first non-complete compilation.
// Most important clauses at the beginning of the list
// will still be sent and used to pre-sort so the local
// CPU can use its cycles for fine-tuning.
mOrderByCompiled = false;
break;
part += clause.ascending() ? " COLLATE NOCASE ASC" : " COLLATE NOCASE DESC";
orderByParts << part;
}
else
{
// Bail out on first non-complete compilation.
// Most important clauses at the beginning of the list
// will still be sent and used to pre-sort so the local
// CPU can use its cycles for fine-tuning.
mOrderByCompiled = false;
break;
}
}
}
}
else
{
mOrderByCompiled = false;
}
else
{
mOrderByCompiled = false;
}

if ( !mOrderByCompiled )
limitAtProvider = false;
if ( !mOrderByCompiled )
limitAtProvider = false;

// also need attributes required by order by
if ( !mOrderByCompiled && mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes && !mRequest.orderBy().isEmpty() )
{
QSet<int> attributeIndexes;
Q_FOREACH ( const QString &attr, mRequest.orderBy().usedAttributes() )
// also need attributes required by order by
if ( !mOrderByCompiled && mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes && !mRequest.orderBy().isEmpty() )
{
attributeIndexes << mSource->mFields.lookupField( attr );
QSet<int> attributeIndexes;
Q_FOREACH ( const QString &attr, mRequest.orderBy().usedAttributes() )
{
attributeIndexes << mSource->mFields.lookupField( attr );
}
attributeIndexes += mRequest.subsetOfAttributes().toSet();
mRequest.setSubsetOfAttributes( attributeIndexes.toList() );
}
attributeIndexes += mRequest.subsetOfAttributes().toSet();
mRequest.setSubsetOfAttributes( attributeIndexes.toList() );
}

// preparing the SQL statement
bool success = prepareStatement( whereClause, limitAtProvider ? mRequest.limit() : -1, orderByParts.join( QStringLiteral( "," ) ) );
if ( !success && useFallbackWhereClause )
{
//try with the fallback where clause, e.g., for cases when using compiled expression failed to prepare
mExpressionCompiled = false;
success = prepareStatement( fallbackWhereClause, -1, orderByParts.join( QStringLiteral( "," ) ) );
}
// preparing the SQL statement
bool success = prepareStatement( whereClause, limitAtProvider ? mRequest.limit() : -1, orderByParts.join( QStringLiteral( "," ) ) );
if ( !success && useFallbackWhereClause )
{
//try with the fallback where clause, e.g., for cases when using compiled expression failed to prepare
mExpressionCompiled = false;
success = prepareStatement( fallbackWhereClause, -1, orderByParts.join( QStringLiteral( "," ) ) );
}

if ( !success )
{
// some error occurred
sqliteStatement = nullptr;
close();
if ( !success )
{
// some error occurred
sqliteStatement = nullptr;
close();
}
}
}

Expand Down

0 comments on commit 86b28ff

Please sign in to comment.