@@ -146,6 +146,18 @@ pub(crate) trait Paginate: Sized {
146
146
options,
147
147
}
148
148
}
149
+
150
+ fn pages_pagination_with_count_query < C > (
151
+ self ,
152
+ options : PaginationOptions ,
153
+ count_query : C ,
154
+ ) -> PaginatedQueryWithCountSubq < Self , C > {
155
+ PaginatedQueryWithCountSubq {
156
+ query : self ,
157
+ count_query,
158
+ options,
159
+ }
160
+ }
149
161
}
150
162
151
163
impl < T > Paginate for T { }
@@ -303,6 +315,61 @@ pub(crate) fn decode_seek<D: for<'a> Deserialize<'a>>(seek: &str) -> anyhow::Res
303
315
Ok ( decoded)
304
316
}
305
317
318
+ #[ derive( Debug ) ]
319
+ pub ( crate ) struct PaginatedQueryWithCountSubq < T , C > {
320
+ query : T ,
321
+ count_query : C ,
322
+ options : PaginationOptions ,
323
+ }
324
+
325
+ impl < T , C > QueryId for PaginatedQueryWithCountSubq < T , C > {
326
+ const HAS_STATIC_QUERY_ID : bool = false ;
327
+ type QueryId = ( ) ;
328
+ }
329
+
330
+ impl <
331
+ T : Query ,
332
+ C : Query + QueryDsl + diesel:: query_dsl:: methods:: SelectDsl < diesel:: dsl:: CountStar > ,
333
+ > Query for PaginatedQueryWithCountSubq < T , C >
334
+ {
335
+ type SqlType = ( T :: SqlType , BigInt ) ;
336
+ }
337
+
338
+ impl < T , C , DB > RunQueryDsl < DB > for PaginatedQueryWithCountSubq < T , C > { }
339
+
340
+ impl < T , C > QueryFragment < Pg > for PaginatedQueryWithCountSubq < T , C >
341
+ where
342
+ T : QueryFragment < Pg > ,
343
+ C : QueryFragment < Pg > ,
344
+ {
345
+ fn walk_ast < ' b > ( & ' b self , mut out : AstPass < ' _ , ' b , Pg > ) -> QueryResult < ( ) > {
346
+ out. push_sql ( "SELECT *, (" ) ;
347
+ self . count_query . walk_ast ( out. reborrow ( ) ) ?;
348
+ out. push_sql ( ") FROM (" ) ;
349
+ self . query . walk_ast ( out. reborrow ( ) ) ?;
350
+ out. push_sql ( ") t LIMIT " ) ;
351
+ out. push_bind_param :: < BigInt , _ > ( & self . options . per_page ) ?;
352
+ if let Some ( offset) = self . options . offset ( ) {
353
+ out. push_sql ( format ! ( " OFFSET {offset}" ) . as_str ( ) ) ;
354
+ }
355
+ Ok ( ( ) )
356
+ }
357
+ }
358
+
359
+ impl < T , C > PaginatedQueryWithCountSubq < T , C > {
360
+ pub ( crate ) fn load < ' a , U > ( self , conn : & mut PgConnection ) -> QueryResult < Paginated < U > >
361
+ where
362
+ Self : LoadQuery < ' a , PgConnection , WithCount < U > > ,
363
+ {
364
+ let options = self . options . clone ( ) ;
365
+ let records_and_total = self . internal_load ( conn) ?. collect :: < QueryResult < _ > > ( ) ?;
366
+ Ok ( Paginated {
367
+ records_and_total,
368
+ options,
369
+ } )
370
+ }
371
+ }
372
+
306
373
#[ cfg( test) ]
307
374
mod tests {
308
375
use super :: * ;
0 commit comments