Skip to content

Commit c0f2b29

Browse files
committed
Compile order by for postgres
1 parent d96a274 commit c0f2b29

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

src/providers/postgres/qgspostgresfeatureiterator.cpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
3535
, mFetched( 0 )
3636
, mFetchGeometry( false )
3737
, mExpressionCompiled( false )
38+
, mOrderByCompiled( false )
3839
, mLastFetch( false )
3940
{
4041
if ( !source->mTransactionConnection )
@@ -111,12 +112,40 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
111112
}
112113
}
113114

114-
bool success = declareCursor( whereClause, limitAtProvider ? mRequest.limit() : -1, false );
115+
QStringList orderByParts;
116+
117+
mOrderByCompiled = true;
118+
119+
Q_FOREACH ( const QgsFeatureRequest::OrderByClause& clause, request.orderBys() )
120+
{
121+
QgsPostgresExpressionCompiler compiler = QgsPostgresExpressionCompiler( source );
122+
QgsExpression expression = clause.expression();
123+
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
124+
{
125+
QString part;
126+
part = compiler.result();
127+
part += clause.ascending() ? " ASC" : " DESC";
128+
part += clause.nullsFirst() ? " NULLS FIRST" : " NULLS LAST";
129+
orderByParts << part;
130+
}
131+
else
132+
{
133+
// Bail out on first non-complete compilation.
134+
// Most important clauses at the beginning of the list
135+
// will still be sent and used to pre-sort so the local
136+
// CPU can use its cycles for fine-tuning.
137+
mOrderByCompiled = false;
138+
limitAtProvider = false;
139+
break;
140+
}
141+
}
142+
143+
bool success = declareCursor( whereClause, limitAtProvider ? mRequest.limit() : -1, false, orderByParts.join( "," ) );
115144
if ( !success && useFallbackWhereClause )
116145
{
117146
//try with the fallback where clause, eg for cases when using compiled expression failed to prepare
118147
mExpressionCompiled = false;
119-
success = declareCursor( fallbackWhereClause, -1, false );
148+
success = declareCursor( fallbackWhereClause, -1, false, orderByParts.join( "," ) );
120149
}
121150

122151
if ( !success )
@@ -232,6 +261,13 @@ bool QgsPostgresFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodT
232261
return methodType == QgsSimplifyMethod::OptimizeForRendering || methodType == QgsSimplifyMethod::PreserveTopology;
233262
}
234263

264+
bool QgsPostgresFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
265+
{
266+
Q_UNUSED( orderBys )
267+
// Preparation has already been done in the constructor, so we just communicate the result
268+
return mOrderByCompiled;
269+
}
270+
235271
bool QgsPostgresFeatureIterator::rewind()
236272
{
237273
if ( mClosed )
@@ -347,7 +383,7 @@ QString QgsPostgresFeatureIterator::whereClauseRect()
347383

348384

349385

350-
bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause, long limit, bool closeOnFail )
386+
bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause, long limit, bool closeOnFail, const QString& orderBy )
351387
{
352388
mFetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && !mSource->mGeometryColumn.isNull();
353389
#if 0
@@ -509,6 +545,9 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause, long
509545
if ( limit >= 0 )
510546
query += QString( " LIMIT %1" ).arg( limit );
511547

548+
if ( !orderBy.isEmpty() )
549+
query += QString( " ORDER BY %1 " ).arg( orderBy );
550+
512551
if ( !mConn->openCursor( mCursorName, query ) )
513552
{
514553

src/providers/postgres/qgspostgresfeatureiterator.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIteratorFromSource<Q
9797
QString whereClauseRect();
9898
bool getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature );
9999
void getFeatureAttribute( int idx, QgsPostgresResult& queryResult, int row, int& col, QgsFeature& feature );
100-
bool declareCursor( const QString& whereClause, long limit = -1, bool closeOnFail = true );
100+
bool declareCursor( const QString& whereClause, long limit = -1, bool closeOnFail = true , const QString& orderBy = QString() );
101101

102102
QString mCursorName;
103103

@@ -124,7 +124,10 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIteratorFromSource<Q
124124
//! returns whether the iterator supports simplify geometries on provider side
125125
virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const override;
126126

127+
virtual bool prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys ) override;
128+
127129
bool mExpressionCompiled;
130+
bool mOrderByCompiled;
128131
bool mLastFetch;
129132
};
130133

0 commit comments

Comments
 (0)