Skip to content

Commit ed61301

Browse files
fixed pagination bug
Signed-off-by: sougata-progress <sougatab@progress.com>
1 parent 768fcb5 commit ed61301

1 file changed

Lines changed: 26 additions & 19 deletions

File tree

components/builder-db/src/models/package.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)