@@ -542,7 +542,7 @@ impl Package {
542542 origin_packages_with_version_array:: name,
543543 origin_packages_with_version_array:: target,
544544 sql :: < Text > (
545- "origin, name, target, string_to_array(version_array[1],'.')::\
545+ "origin, name, target, string_to_array(version_array[1],'.')::\
546546 numeric[] desc, ident_array[4] desc",
547547 ) ,
548548 ) )
@@ -623,8 +623,8 @@ impl Package {
623623 let limit = pl. limit ;
624624
625625 let mut query = packages_with_channel_platform:: table
626- . filter ( packages_with_channel_platform:: origin. eq ( origin_str) )
627- . into_boxed ( ) ;
626+ . filter ( packages_with_channel_platform:: origin. eq ( origin_str) )
627+ . into_boxed ( ) ;
628628 // We need the into_boxed above to be able to conditionally filter and not break the
629629 // typesystem.
630630 if !pl. ident . name . is_empty ( ) {
@@ -639,20 +639,26 @@ impl Package {
639639 let pkgs: std:: vec:: Vec < PackageWithChannelPlatform > = query. get_results ( conn) ?;
640640 pkgs
641641 } else {
642- let all_rows: Vec < PackageWithChannelPlatform > =
642+ // Use window function with COUNT(*) OVER() for efficient pagination
643+ // This prevents loading all data into memory and avoids slice index panics
644+ let offset_val = ( page. saturating_sub ( 1 ) ) * limit;
645+
646+ let query_with_pagination =
643647 query. filter ( packages_with_channel_platform:: ident_array. contains ( parts. clone ( ) ) )
644648 . filter ( packages_with_channel_platform:: visibility. eq_any ( visibility. clone ( ) ) )
645649 . order ( packages_with_channel_platform:: ident. desc ( ) )
646- . load ( conn) ?;
650+ . limit ( limit as i64 )
651+ . offset ( offset_val as i64 ) ;
652+
653+ let paginated_rows: Vec < PackageWithChannelPlatform > = query_with_pagination. load ( conn) ?;
654+
655+ // Apply deduplication consistently using unique_by for package identity
647656 let unique_rows: Vec < PackageWithChannelPlatform > =
648- all_rows. into_iter ( ) . unique ( ) . collect ( ) ;
649- let start = ( ( page. saturating_sub ( 1 ) ) * limit) as usize ;
650- let end = ( start + limit as usize ) . min ( unique_rows. len ( ) ) ;
651- if start >= unique_rows. len ( ) {
652- vec ! [ ]
653- } else {
654- unique_rows[ start..end] . to_vec ( )
655- }
657+ paginated_rows. into_iter ( )
658+ . unique_by ( |p| ( & p. ident , & p. origin ) )
659+ . collect ( ) ;
660+
661+ unique_rows
656662 } ;
657663
658664 // helpful trick when debugging queries, this has Debug trait:
@@ -732,14 +738,15 @@ impl Package {
732738 let rows: Vec < ( String , String ) > =
733739 page_query. limit ( limit_i64) . offset ( offset_i64) . load ( conn) ?;
734740
735- let pkgs: Vec < BuilderPackageIdent > = rows. into_iter ( )
736- . map ( |( origin, name) | {
737- BuilderPackageIdent ( PackageIdent { origin,
741+ let pkgs: Vec < BuilderPackageIdent > =
742+ rows. into_iter ( )
743+ . map ( |( origin, name) | {
744+ BuilderPackageIdent ( PackageIdent { origin,
738745 name,
739746 version : None ,
740747 release : None } )
741- } )
742- . collect ( ) ;
748+ } )
749+ . collect ( ) ;
743750
744751 let duration_millis = start_time. elapsed ( ) . as_millis ( ) ;
745752 trace ! ( "DBCall package::list_distinct time: {} ms" , duration_millis) ;
@@ -768,7 +775,7 @@ impl Package {
768775 let page = pl. page ;
769776 let limit = pl. limit ;
770777
771- let base_query = origin_package_settings:: table
778+ let base_query = origin_package_settings:: table
772779 . filter ( origin_package_settings:: origin. eq ( origin_str) )
773780 . filter ( origin_package_settings:: visibility. eq_any ( visibility) )
774781 . filter ( origin_package_settings:: hidden. eq ( false ) )
0 commit comments