Skip to content

Commit

Permalink
Merge pull request #5437 from m-kuhn/pgquick
Browse files Browse the repository at this point in the history
[postgres] respect empty FilterFids list
  • Loading branch information
m-kuhn authored Oct 25, 2017
2 parents a9f8e60 + 62f2091 commit bb8bad0
Showing 1 changed file with 83 additions and 75 deletions.
158 changes: 83 additions & 75 deletions src/providers/postgres/qgspostgresfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
, mLastFetch( false )
, mFilterRequiresGeometry( false )
{
if ( request.filterType() == QgsFeatureRequest::FilterFids && request.filterFids().isEmpty() )
{
mClosed = true;
iteratorClosed();
return;
}

if ( !source->mTransactionConnection )
{
mConn = QgsPostgresConnPool::instance()->acquireConnection( mSource->mConnInfo );
Expand Down Expand Up @@ -65,7 +72,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
catch ( QgsCsException & )
{
// can't reproject mFilterRect
mClosed = true;
close();
return;
}

Expand Down Expand Up @@ -136,98 +143,99 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
}
}

QStringList orderByParts;
if ( !mClosed )
{
QStringList orderByParts;

mOrderByCompiled = true;
mOrderByCompiled = true;

// THIS CODE IS BROKEN - since every retrieved column is cast as text during declareCursor, this method of sorting will always be
// performed using a text sort.
// TODO - fix ordering by so that instead of
// SELECT my_int_col::text FROM some_table ORDER BY my_int_col
// we instead use
// SELECT my_int_col::text FROM some_table ORDER BY some_table.my_int_col
// but that's non-trivial
// THIS CODE IS BROKEN - since every retrieved column is cast as text during declareCursor, this method of sorting will always be
// performed using a text sort.
// TODO - fix ordering by so that instead of
// SELECT my_int_col::text FROM some_table ORDER BY my_int_col
// we instead use
// SELECT my_int_col::text FROM some_table ORDER BY some_table.my_int_col
// but that's non-trivial
#if 0
if ( QgsSettings().value( "qgis/compileExpressions", true ).toBool() )
{
Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, request.orderBy() )
if ( QgsSettings().value( "qgis/compileExpressions", true ).toBool() )
{
QgsPostgresExpressionCompiler compiler = QgsPostgresExpressionCompiler( source );
QgsExpression expression = clause.expression();
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
{
QString part;
part = compiler.result();
part += clause.ascending() ? " ASC" : " DESC";
part += clause.nullsFirst() ? " NULLS FIRST" : " NULLS LAST";
orderByParts << part;
}
else
Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, request.orderBy() )
{
// 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;
QgsPostgresExpressionCompiler compiler = QgsPostgresExpressionCompiler( source );
QgsExpression expression = clause.expression();
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
{
QString part;
part = compiler.result();
part += clause.ascending() ? " ASC" : " DESC";
part += clause.nullsFirst() ? " NULLS FIRST" : " NULLS LAST";
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
else
#endif
{
mOrderByCompiled = false;
}
{
mOrderByCompiled = mRequest.orderBy().isEmpty();
}

// ensure that all attributes required for order by are fetched
if ( !mOrderByCompiled && mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
{
QgsAttributeList attrs = mRequest.subsetOfAttributes();
Q_FOREACH ( const QString &attr, mRequest.orderBy().usedAttributes() )
// ensure that all attributes required for order by are fetched
if ( !mOrderByCompiled && mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
{
int attrIndex = mSource->mFields.lookupField( attr );
if ( !attrs.contains( attrIndex ) )
attrs << attrIndex;
QgsAttributeList attrs = mRequest.subsetOfAttributes();
Q_FOREACH ( const QString &attr, mRequest.orderBy().usedAttributes() )
{
int attrIndex = mSource->mFields.lookupField( attr );
if ( !attrs.contains( attrIndex ) )
attrs << attrIndex;
}
mRequest.setSubsetOfAttributes( attrs );
}
mRequest.setSubsetOfAttributes( attrs );
}

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

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

if ( !success && !orderByParts.isEmpty() )
{
//try with no order by clause
success = declareCursor( whereClause, -1, false );
if ( success )
mOrderByCompiled = false;
}
if ( !success && !orderByParts.isEmpty() )
{
//try with no order by clause
success = declareCursor( whereClause, -1, false );
if ( success )
mOrderByCompiled = false;
}

if ( !success && useFallbackWhereClause && !orderByParts.isEmpty() )
{
//try with no expression compilation AND no order by clause
success = declareCursor( fallbackWhereClause, -1, false );
if ( success )
if ( !success && useFallbackWhereClause && !orderByParts.isEmpty() )
{
mExpressionCompiled = false;
mOrderByCompiled = false;
//try with no expression compilation AND no order by clause
success = declareCursor( fallbackWhereClause, -1, false );
if ( success )
{
mExpressionCompiled = false;
mOrderByCompiled = false;
}
}
}

if ( !success )
{
close();
mClosed = true;
iteratorClosed();
if ( !success )
{
close();
}
}

mFetched = 0;
Expand Down

0 comments on commit bb8bad0

Please sign in to comment.