@@ -228,7 +228,7 @@ pub async fn list_crates(
228228 let seek = seek. unwrap ( ) ;
229229 if let Some ( condition) = seek
230230 . decode ( & pagination. page ) ?
231- . map ( |s| filter_params. seek_after ( & s) )
231+ . map ( |s| filter_params. seek ( & s, is_forward ) )
232232 {
233233 query = query. filter ( condition) ;
234234 }
@@ -506,7 +506,7 @@ impl FilterParams {
506506 query
507507 }
508508
509- fn seek_after ( & self , seek_payload : & seek:: SeekPayload ) -> BoxedCondition < ' _ > {
509+ fn seek ( & self , seek_payload : & seek:: SeekPayload , is_forward : bool ) -> BoxedCondition < ' _ > {
510510 use seek:: * ;
511511
512512 let crates_aliased = alias ! ( crates as crates_aliased) ;
@@ -518,63 +518,85 @@ impl FilterParams {
518518 } ;
519519 let conditions: Vec < BoxedCondition < ' _ > > = match * seek_payload {
520520 SeekPayload :: Name ( Name { id } ) => {
521- // Equivalent of:
522- // ```
523- // WHERE name > name'
524- // ORDER BY name ASC
525- // ```
526- vec ! [ Box :: new( crates:: name. nullable( ) . gt( crate_name_by_id( id) ) ) ]
521+ if is_forward {
522+ // Equivalent of:
523+ // ```
524+ // WHERE name > name'
525+ // ORDER BY name ASC
526+ // ```
527+ vec ! [ Box :: new( crates:: name. nullable( ) . gt( crate_name_by_id( id) ) ) ]
528+ } else {
529+ vec ! [ Box :: new( crates:: name. nullable( ) . lt( crate_name_by_id( id) ) ) ]
530+ }
527531 }
528532 SeekPayload :: New ( New { created_at, id } ) => {
529- // Equivalent of:
530- // ```
531- // WHERE (created_at = created_at' AND id < id') OR created_at < created_at'
532- // ORDER BY created_at DESC, id DESC
533- // ```
534- vec ! [
535- Box :: new(
536- crates:: created_at
537- . eq( created_at)
538- . and( crates:: id. lt( id) )
539- . nullable( ) ,
540- ) ,
541- Box :: new( crates:: created_at. lt( created_at) . nullable( ) ) ,
542- ]
533+ if is_forward {
534+ // Equivalent of:
535+ // ```
536+ // WHERE (created_at = created_at' AND id < id') OR created_at < created_at'
537+ // ORDER BY created_at DESC, id DESC
538+ // ```
539+ vec ! [
540+ Box :: new(
541+ crates:: created_at
542+ . eq( created_at)
543+ . and( crates:: id. lt( id) )
544+ . nullable( ) ,
545+ ) ,
546+ Box :: new( crates:: created_at. lt( created_at) . nullable( ) ) ,
547+ ]
548+ } else {
549+ vec ! [
550+ Box :: new(
551+ crates:: created_at
552+ . eq( created_at)
553+ . and( crates:: id. gt( id) )
554+ . nullable( ) ,
555+ ) ,
556+ Box :: new( crates:: created_at. gt( created_at) . nullable( ) ) ,
557+ ]
558+ }
543559 }
544560 SeekPayload :: RecentUpdates ( RecentUpdates { updated_at, id } ) => {
545- // Equivalent of:
546- // ```
547- // WHERE (updated_at = updated_at' AND id < id') OR updated_at < updated_at'
548- // ORDER BY updated_at DESC, id DESC
549- // ```
550- vec ! [
551- Box :: new(
552- crates:: updated_at
553- . eq( updated_at)
554- . and( crates:: id. lt( id) )
555- . nullable( ) ,
556- ) ,
557- Box :: new( crates:: updated_at. lt( updated_at) . nullable( ) ) ,
558- ]
561+ if is_forward {
562+ // Equivalent of:
563+ // ```
564+ // WHERE (updated_at = updated_at' AND id < id') OR updated_at < updated_at'
565+ // ORDER BY updated_at DESC, id DESC
566+ // ```
567+ vec ! [
568+ Box :: new(
569+ crates:: updated_at
570+ . eq( updated_at)
571+ . and( crates:: id. lt( id) )
572+ . nullable( ) ,
573+ ) ,
574+ Box :: new( crates:: updated_at. lt( updated_at) . nullable( ) ) ,
575+ ]
576+ } else {
577+ vec ! [
578+ Box :: new(
579+ crates:: updated_at
580+ . eq( updated_at)
581+ . and( crates:: id. gt( id) )
582+ . nullable( ) ,
583+ ) ,
584+ Box :: new( crates:: updated_at. gt( updated_at) . nullable( ) ) ,
585+ ]
586+ }
559587 }
560588 SeekPayload :: RecentDownloads ( RecentDownloads {
561589 recent_downloads,
562590 id,
563591 } ) => {
564- // Equivalent of:
565- // for recent_downloads is not None:
566- // ```
567- // WHERE (recent_downloads = recent_downloads' AND id < id')
568- // OR (recent_downloads < recent_downloads' OR recent_downloads IS NULL)
569- // ORDER BY recent_downloads DESC NULLS LAST, id DESC
570- // ```
571- // for recent_downloads is None:
572- // ```
573- // WHERE (recent_downloads IS NULL AND id < id')
574- // ORDER BY recent_downloads DESC NULLS LAST, id DESC
575- // ```
576- match recent_downloads {
577- Some ( dl) => {
592+ match ( recent_downloads, is_forward) {
593+ ( Some ( dl) , true ) => {
594+ // Equivalent of:
595+ // ```
596+ // WHERE (recent_downloads = recent_downloads' AND id < id')
597+ // OR (recent_downloads < recent_downloads' OR recent_downloads IS NULL)
598+ // ORDER BY recent_downloads DESC NULLS LAST, id DESC
599+ // ```
578600 vec ! [
579601 Box :: new(
580602 recent_crate_downloads:: downloads
@@ -590,80 +612,157 @@ impl FilterParams {
590612 ) ,
591613 ]
592614 }
593- None => {
615+ ( None , true ) => {
616+ // Equivalent of:
617+ // ```
618+ // WHERE (recent_downloads IS NULL AND id < id')
619+ // ORDER BY recent_downloads DESC NULLS LAST, id DESC
620+ // ```
594621 vec ! [ Box :: new(
595622 recent_crate_downloads:: downloads
596623 . is_null( )
597624 . and( crates:: id. lt( id) )
598625 . nullable( ) ,
599626 ) ]
600627 }
628+ ( Some ( dl) , false ) => {
629+ // Equivalent of:
630+ // ```
631+ // WHERE (recent_downloads = recent_downloads' AND id > id')
632+ // OR (recent_downloads > recent_downloads')
633+ // ORDER BY recent_downloads ASC NULLS FIRST, id ASC
634+ // ```
635+ vec ! [
636+ Box :: new(
637+ recent_crate_downloads:: downloads
638+ . eq( dl)
639+ . and( crates:: id. gt( id) )
640+ . nullable( ) ,
641+ ) ,
642+ Box :: new( recent_crate_downloads:: downloads. gt( dl) . nullable( ) ) ,
643+ ]
644+ }
645+ ( None , false ) => {
646+ // Equivalent of:
647+ // ```
648+ // WHERE (recent_downloads IS NULL AND id > id')
649+ // OR (recent_downloads IS NOT NULL)
650+ // ORDER BY recent_downloads ASC NULLS FIRST, id ASC
651+ // ```
652+ vec ! [
653+ Box :: new(
654+ recent_crate_downloads:: downloads
655+ . is_null( )
656+ . and( crates:: id. gt( id) )
657+ . nullable( ) ,
658+ ) ,
659+ Box :: new( recent_crate_downloads:: downloads. is_not_null( ) . nullable( ) ) ,
660+ ]
661+ }
601662 }
602663 }
603664 SeekPayload :: Downloads ( Downloads { downloads, id } ) => {
604- // Equivalent of:
605- // ```
606- // WHERE (downloads = downloads' AND id < id') OR downloads < downloads'
607- // ORDER BY downloads DESC, id DESC
608- // ```
609- vec ! [
610- Box :: new(
611- crate_downloads:: downloads
612- . eq( downloads)
613- . and( crates:: id. lt( id) )
614- . nullable( ) ,
615- ) ,
616- Box :: new( crate_downloads:: downloads. lt( downloads) . nullable( ) ) ,
617- ]
665+ if is_forward {
666+ // Equivalent of:
667+ // ```
668+ // WHERE (downloads = downloads' AND id < id') OR downloads < downloads'
669+ // ORDER BY downloads DESC, id DESC
670+ // ```
671+ vec ! [
672+ Box :: new(
673+ crate_downloads:: downloads
674+ . eq( downloads)
675+ . and( crates:: id. lt( id) )
676+ . nullable( ) ,
677+ ) ,
678+ Box :: new( crate_downloads:: downloads. lt( downloads) . nullable( ) ) ,
679+ ]
680+ } else {
681+ vec ! [
682+ Box :: new(
683+ crate_downloads:: downloads
684+ . eq( downloads)
685+ . and( crates:: id. gt( id) )
686+ . nullable( ) ,
687+ ) ,
688+ Box :: new( crate_downloads:: downloads. gt( downloads) . nullable( ) ) ,
689+ ]
690+ }
618691 }
619692 SeekPayload :: Query ( Query { exact_match, id } ) => {
620- // Equivalent of:
621- // ```
622- // WHERE (exact_match = exact_match' AND name > name') OR exact_match < exact_match'
623- // ORDER BY exact_match DESC, NAME ASC
624- // ```
625693 let q_string = self . q_string . as_ref ( ) . expect ( "q_string should not be None" ) ;
626694 let name_exact_match = Crate :: with_name ( q_string) ;
627- vec ! [
628- Box :: new(
629- name_exact_match
630- . eq( exact_match)
631- . and( crates:: name. nullable( ) . gt( crate_name_by_id( id) ) )
632- . nullable( ) ,
633- ) ,
634- Box :: new( name_exact_match. lt( exact_match) . nullable( ) ) ,
635- ]
695+ if is_forward {
696+ // Equivalent of:
697+ // ```
698+ // WHERE (exact_match = exact_match' AND name > name') OR exact_match < exact_match'
699+ // ORDER BY exact_match DESC, NAME ASC
700+ // ```
701+ vec ! [
702+ Box :: new(
703+ name_exact_match
704+ . eq( exact_match)
705+ . and( crates:: name. nullable( ) . gt( crate_name_by_id( id) ) )
706+ . nullable( ) ,
707+ ) ,
708+ Box :: new( name_exact_match. lt( exact_match) . nullable( ) ) ,
709+ ]
710+ } else {
711+ vec ! [
712+ Box :: new(
713+ name_exact_match
714+ . eq( exact_match)
715+ . and( crates:: name. nullable( ) . lt( crate_name_by_id( id) ) )
716+ . nullable( ) ,
717+ ) ,
718+ Box :: new( name_exact_match. gt( exact_match) . nullable( ) ) ,
719+ ]
720+ }
636721 }
637722 SeekPayload :: Relevance ( Relevance {
638723 exact_match : exact,
639724 rank : rank_in,
640725 id,
641726 } ) => {
642- // Equivalent of:
643- // ```
644- // WHERE (exact_match = exact_match' AND rank = rank' AND name > name')
645- // OR (exact_match = exact_match' AND rank < rank')
646- // OR exact_match < exact_match'
647- // ORDER BY exact_match DESC, rank DESC, name ASC
648- // ```
649727 let q_string = self . q_string . as_ref ( ) . expect ( "q_string should not be None" ) ;
650728 let q = plainto_tsquery_with_search_config (
651729 TsConfigurationByName ( "english" ) ,
652730 q_string. as_str ( ) ,
653731 ) ;
654732 let rank = ts_rank_cd ( crates:: textsearchable_index_col, q) ;
655733 let name_exact_match = Crate :: with_name ( q_string. as_str ( ) ) ;
656- vec ! [
657- Box :: new(
658- name_exact_match
659- . eq( exact)
660- . and( rank. eq( rank_in) )
661- . and( crates:: name. nullable( ) . gt( crate_name_by_id( id) ) )
662- . nullable( ) ,
663- ) ,
664- Box :: new( name_exact_match. eq( exact) . and( rank. lt( rank_in) ) . nullable( ) ) ,
665- Box :: new( name_exact_match. lt( exact) . nullable( ) ) ,
666- ]
734+ if is_forward {
735+ // Equivalent of:
736+ // ```
737+ // WHERE (exact_match = exact_match' AND rank = rank' AND name > name')
738+ // OR (exact_match = exact_match' AND rank < rank')
739+ // OR exact_match < exact_match'
740+ // ORDER BY exact_match DESC, rank DESC, name ASC
741+ // ```
742+ vec ! [
743+ Box :: new(
744+ name_exact_match
745+ . eq( exact)
746+ . and( rank. eq( rank_in) )
747+ . and( crates:: name. nullable( ) . gt( crate_name_by_id( id) ) )
748+ . nullable( ) ,
749+ ) ,
750+ Box :: new( name_exact_match. eq( exact) . and( rank. lt( rank_in) ) . nullable( ) ) ,
751+ Box :: new( name_exact_match. lt( exact) . nullable( ) ) ,
752+ ]
753+ } else {
754+ vec ! [
755+ Box :: new(
756+ name_exact_match
757+ . eq( exact)
758+ . and( rank. eq( rank_in) )
759+ . and( crates:: name. nullable( ) . lt( crate_name_by_id( id) ) )
760+ . nullable( ) ,
761+ ) ,
762+ Box :: new( name_exact_match. eq( exact) . and( rank. gt( rank_in) ) . nullable( ) ) ,
763+ Box :: new( name_exact_match. gt( exact) . nullable( ) ) ,
764+ ]
765+ }
667766 }
668767 } ;
669768
0 commit comments