QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeatureSource* source, bool ownSource, const QgsFeatureRequest& request ) : QgsAbstractFeatureIteratorFromSource<QgsSpatiaLiteFeatureSource>( source, ownSource, request ) , sqliteStatement( NULL ) , mExpressionCompiled( false ) { mHandle = QgsSpatiaLiteConnPool::instance()->acquireConnection( mSource->mSqlitePath ); mFetchGeometry = !mSource->mGeometryColumn.isNull() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ); mHasPrimaryKey = !mSource->mPrimaryKey.isEmpty(); mRowNumber = 0; QStringList whereClauses; bool useFallbackWhereClause = false; QString fallbackWhereClause; QString whereClause; //beware - limitAtProvider needs to be set to false if the request cannot be completely handled //by the provider (eg utilising QGIS expression filters) bool limitAtProvider = ( mRequest.limit() >= 0 ); if ( !request.filterRect().isNull() && !mSource->mGeometryColumn.isNull() ) { // some kind of MBR spatial filtering is required whereClause = whereClauseRect(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } if ( !mSource->mSubsetString.isEmpty() ) { whereClause = "( " + mSource->mSubsetString + ')'; if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } if ( request.filterType() == QgsFeatureRequest::FilterFid ) { whereClause = whereClauseFid(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } else if ( request.filterType() == QgsFeatureRequest::FilterFids ) { whereClause = whereClauseFids(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } //IMPORTANT - this MUST be the last clause added! else if ( request.filterType() == QgsFeatureRequest::FilterExpression ) { if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() ) { QgsSpatiaLiteExpressionCompiler compiler = QgsSpatiaLiteExpressionCompiler( source ); QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() ); if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial ) { whereClause = compiler.result(); if ( !whereClause.isEmpty() ) { useFallbackWhereClause = true; fallbackWhereClause = whereClauses.join( " AND " ); whereClauses.append( whereClause ); //if only partial success when compiling expression, we need to double-check results using QGIS' expressions mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete ); } } if ( result != QgsSqlExpressionCompiler::Complete ) { //can't apply limit at provider side as we need to check all results using QGIS expressions limitAtProvider = false; } } else { limitAtProvider = false; } } whereClause = whereClauses.join( " AND " ); // preparing the SQL statement bool success = prepareStatement( whereClause, limitAtProvider ? mRequest.limit() : -1 ); if ( !success && useFallbackWhereClause ) { //try with the fallback where clause, eg for cases when using compiled expression failed to prepare mExpressionCompiled = false; success = prepareStatement( fallbackWhereClause, -1 ); } if ( !success ) { // some error occurred sqliteStatement = NULL; close(); } }
QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeatureSource* source, bool ownSource, const QgsFeatureRequest& request ) : QgsAbstractFeatureIteratorFromSource<QgsSpatiaLiteFeatureSource>( source, ownSource, request ) , sqliteStatement( nullptr ) , mExpressionCompiled( false ) { mHandle = QgsSpatiaLiteConnPool::instance()->acquireConnection( mSource->mSqlitePath ); mFetchGeometry = !mSource->mGeometryColumn.isNull() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ); mHasPrimaryKey = !mSource->mPrimaryKey.isEmpty(); mRowNumber = 0; QStringList whereClauses; bool useFallbackWhereClause = false; QString fallbackWhereClause; QString whereClause; //beware - limitAtProvider needs to be set to false if the request cannot be completely handled //by the provider (eg utilising QGIS expression filters) bool limitAtProvider = ( mRequest.limit() >= 0 ); if ( !request.filterRect().isNull() && !mSource->mGeometryColumn.isNull() ) { // some kind of MBR spatial filtering is required whereClause = whereClauseRect(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } if ( !mSource->mSubsetString.isEmpty() ) { whereClause = "( " + mSource->mSubsetString + ')'; if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } if ( request.filterType() == QgsFeatureRequest::FilterFid ) { whereClause = whereClauseFid(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } else if ( request.filterType() == QgsFeatureRequest::FilterFids ) { whereClause = whereClauseFids(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } //IMPORTANT - this MUST be the last clause added! else if ( request.filterType() == QgsFeatureRequest::FilterExpression ) { // ensure that all attributes required for expression filter are being fetched if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes && request.filterType() == QgsFeatureRequest::FilterExpression ) { QgsAttributeList attrs = request.subsetOfAttributes(); Q_FOREACH ( const QString& field, request.filterExpression()->referencedColumns() ) { int attrIdx = mSource->mFields.fieldNameIndex( field ); if ( !attrs.contains( attrIdx ) ) attrs << attrIdx; } mRequest.setSubsetOfAttributes( attrs ); } if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() ) { QgsSpatiaLiteExpressionCompiler compiler = QgsSpatiaLiteExpressionCompiler( source ); QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() ); if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial ) { whereClause = compiler.result(); if ( !whereClause.isEmpty() ) { useFallbackWhereClause = true; fallbackWhereClause = whereClauses.join( " AND " ); whereClauses.append( whereClause ); //if only partial success when compiling expression, we need to double-check results using QGIS' expressions mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete ); } } if ( result != QgsSqlExpressionCompiler::Complete ) { //can't apply limit at provider side as we need to check all results using QGIS expressions limitAtProvider = false; } } else { limitAtProvider = false; } }
QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeatureSource* source, bool ownSource, const QgsFeatureRequest& request ) : QgsAbstractFeatureIteratorFromSource<QgsSpatiaLiteFeatureSource>( source, ownSource, request ) , sqliteStatement( nullptr ) , mExpressionCompiled( false ) { mHandle = QgsSpatiaLiteConnPool::instance()->acquireConnection( mSource->mSqlitePath ); mFetchGeometry = !mSource->mGeometryColumn.isNull() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ); mHasPrimaryKey = !mSource->mPrimaryKey.isEmpty(); mRowNumber = 0; QStringList whereClauses; bool useFallbackWhereClause = false; QString fallbackWhereClause; QString whereClause; //beware - limitAtProvider needs to be set to false if the request cannot be completely handled //by the provider (eg utilising QGIS expression filters) bool limitAtProvider = ( mRequest.limit() >= 0 ); if ( !request.filterRect().isNull() && !mSource->mGeometryColumn.isNull() ) { // some kind of MBR spatial filtering is required whereClause = whereClauseRect(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } if ( !mSource->mSubsetString.isEmpty() ) { whereClause = "( " + mSource->mSubsetString + ')'; if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } if ( request.filterType() == QgsFeatureRequest::FilterFid ) { whereClause = whereClauseFid(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } else if ( request.filterType() == QgsFeatureRequest::FilterFids ) { whereClause = whereClauseFids(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } //IMPORTANT - this MUST be the last clause added! else if ( request.filterType() == QgsFeatureRequest::FilterExpression ) { if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() ) { QgsSpatiaLiteExpressionCompiler compiler = QgsSpatiaLiteExpressionCompiler( source ); QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() ); if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial ) { whereClause = compiler.result(); if ( !whereClause.isEmpty() ) { useFallbackWhereClause = true; fallbackWhereClause = whereClauses.join( " AND " ); whereClauses.append( whereClause ); //if only partial success when compiling expression, we need to double-check results using QGIS' expressions mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete ); } } if ( result != QgsSqlExpressionCompiler::Complete ) { //can't apply limit at provider side as we need to check all results using QGIS expressions limitAtProvider = false; } } else { limitAtProvider = false; } } whereClause = whereClauses.join( " AND " ); // Setup the order by QStringList orderByParts; mOrderByCompiled = true; if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() ) { Q_FOREACH ( const QgsFeatureRequest::OrderByClause& clause, request.orderBy() ) { QgsSpatiaLiteExpressionCompiler compiler = QgsSpatiaLiteExpressionCompiler( source ); QgsExpression expression = clause.expression(); if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete ) { QString part; part = compiler.result(); if ( clause.nullsFirst() ) orderByParts << QString( "%1 IS NOT NULL" ).arg( part ); else orderByParts << QString( "%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; } } }
QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeatureSource* source, bool ownSource, const QgsFeatureRequest& request ) : QgsAbstractFeatureIteratorFromSource<QgsSpatiaLiteFeatureSource>( source, ownSource, request ) , sqliteStatement( NULL ) , mExpressionCompiled( false ) { mHandle = QgsSpatiaLiteConnPool::instance()->acquireConnection( mSource->mSqlitePath ); mFetchGeometry = !mSource->mGeometryColumn.isNull() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ); mHasPrimaryKey = !mSource->mPrimaryKey.isEmpty(); mRowNumber = 0; QStringList whereClauses; QString whereClause; if ( !request.filterRect().isNull() && !mSource->mGeometryColumn.isNull() ) { // some kind of MBR spatial filtering is required whereClause = whereClauseRect(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } if ( request.filterType() == QgsFeatureRequest::FilterFid ) { whereClause = whereClauseFid(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } else if ( request.filterType() == QgsFeatureRequest::FilterFids ) { whereClause = whereClauseFids(); if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } else if ( request.filterType() == QgsFeatureRequest::FilterExpression && QSettings().value( "/qgis/compileExpressions", true ).toBool() ) { QgsSpatiaLiteExpressionCompiler compiler = QgsSpatiaLiteExpressionCompiler( source ); QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() ); if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial ) { whereClause = compiler.result(); if ( !whereClause.isEmpty() ) { whereClauses.append( whereClause ); //if only partial success when compiling expression, we need to double-check results using QGIS' expressions mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete ); } } } if ( !mSource->mSubsetString.isEmpty() ) { whereClause = "( " + mSource->mSubsetString + ')'; if ( ! whereClause.isEmpty() ) { whereClauses.append( whereClause ); } } whereClause = whereClauses.join( " AND " ); // preparing the SQL statement if ( !prepareStatement( whereClause ) ) { // some error occurred sqliteStatement = NULL; close(); return; } }