|
@@ -53,7 +53,7 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature |
|
|
catch ( QgsCsException & ) |
|
|
{ |
|
|
// can't reproject mFilterRect |
|
|
mClosed = true; |
|
|
close(); |
|
|
return; |
|
|
} |
|
|
|
|
@@ -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! |
|
@@ -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(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|