@@ -35,6 +35,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
35
35
, mFetched( 0 )
36
36
, mFetchGeometry( false )
37
37
, mExpressionCompiled( false )
38
+ , mOrderByCompiled( false )
38
39
, mLastFetch( false )
39
40
{
40
41
if ( !source->mTransactionConnection )
@@ -111,12 +112,40 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
111
112
}
112
113
}
113
114
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 ( " ," ) );
115
144
if ( !success && useFallbackWhereClause )
116
145
{
117
146
// try with the fallback where clause, eg for cases when using compiled expression failed to prepare
118
147
mExpressionCompiled = false ;
119
- success = declareCursor ( fallbackWhereClause, -1 , false );
148
+ success = declareCursor ( fallbackWhereClause, -1 , false , orderByParts. join ( " , " ) );
120
149
}
121
150
122
151
if ( !success )
@@ -232,6 +261,13 @@ bool QgsPostgresFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodT
232
261
return methodType == QgsSimplifyMethod::OptimizeForRendering || methodType == QgsSimplifyMethod::PreserveTopology;
233
262
}
234
263
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
+
235
271
bool QgsPostgresFeatureIterator::rewind ()
236
272
{
237
273
if ( mClosed )
@@ -347,7 +383,7 @@ QString QgsPostgresFeatureIterator::whereClauseRect()
347
383
348
384
349
385
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 )
351
387
{
352
388
mFetchGeometry = !( mRequest .flags () & QgsFeatureRequest::NoGeometry ) && !mSource ->mGeometryColumn .isNull ();
353
389
#if 0
@@ -509,6 +545,9 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause, long
509
545
if ( limit >= 0 )
510
546
query += QString ( " LIMIT %1" ).arg ( limit );
511
547
548
+ if ( !orderBy.isEmpty () )
549
+ query += QString ( " ORDER BY %1 " ).arg ( orderBy );
550
+
512
551
if ( !mConn ->openCursor ( mCursorName , query ) )
513
552
{
514
553
0 commit comments