Skip to content

Commit

Permalink
perf(query): optimize packages list SQL query
Browse files Browse the repository at this point in the history
  • Loading branch information
QaidVoid committed Jan 27, 2025
1 parent 0b84535 commit 826f343
Show file tree
Hide file tree
Showing 14 changed files with 191 additions and 87 deletions.
58 changes: 23 additions & 35 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ futures = "0.3.31"
rayon = "1.10.0"
regex = { version = "1.11.1", default-features = false, features = ["unicode-case", "unicode-perl", "std"] }
reqwest = { version = "0.12.9", default-features = false, features = ["rustls-tls", "blocking", "http2", "json", "stream"] }
rusqlite = { version = "0.32.1", features = ["bundled", "rusqlite-macros"] }
rusqlite = { version = "0.33.0", features = ["bundled", "rusqlite-macros"] }
serde = { version = "1.0.217", features = ["derive"] }
serde_json = { version = "1.0.135", features = ["indexmap"] }
soar-dl = "0.3.2"
soar-dl = "0.3.3"
9 changes: 7 additions & 2 deletions soar-cli/src/inspect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ use std::fmt::Display;
use futures::StreamExt;
use indicatif::HumanBytes;
use soar_core::{
database::packages::PackageQueryBuilder, package::query::PackageQuery, SoarResult,
database::{
models::Package,
packages::{PackageQueryBuilder, PaginatedResponse},
},
package::query::PackageQuery,
SoarResult,
};
use tracing::{error, info};

Expand Down Expand Up @@ -31,7 +36,7 @@ pub async fn inspect_log(package: &str, inspect_type: InspectType) -> SoarResult
let builder = PackageQueryBuilder::new(repo_db).limit(1);
let builder = query.apply_filters(builder);

let packages = builder.load()?;
let packages: PaginatedResponse<Package> = builder.load()?;

if packages.items.is_empty() {
error!("Package {} not found", package);
Expand Down
8 changes: 4 additions & 4 deletions soar-cli/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use soar_core::{
config::get_config,
database::{
models::{InstalledPackage, Package, PackageExt},
packages::{FilterCondition, PackageQueryBuilder, ProvideStrategy},
packages::{FilterCondition, PackageQueryBuilder, PaginatedResponse, ProvideStrategy},
},
error::SoarError,
package::{
Expand Down Expand Up @@ -144,7 +144,7 @@ fn resolve_packages(
.items;

if query.name.is_none() && query.pkg_id.is_some() {
let packages = builder.load()?;
let packages: PaginatedResponse<Package> = builder.load()?;
for pkg in packages.items {
let existing_install = installed_packages
.iter()
Expand Down Expand Up @@ -415,10 +415,10 @@ async fn install_single_package(

if let Some(provides) = &target.package.provides {
for provide in provides {
if let Some(ref target) = provide.target_name {
if let Some(ref target) = provide.target {
let real_path = install_dir.join(provide.name.clone());
let is_symlink = match provide.strategy {
ProvideStrategy::KeepTargetOnly | ProvideStrategy::KeepBoth => true,
Some(ProvideStrategy::KeepTargetOnly) | Some(ProvideStrategy::KeepBoth) => true,
_ => false,
};
if is_symlink {
Expand Down
53 changes: 48 additions & 5 deletions soar-cli/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use rusqlite::Connection;
use soar_core::{
config::get_config,
database::{
models::Package,
packages::{FilterCondition, PackageQueryBuilder, SortDirection},
models::{FromRow, Package},
packages::{FilterCondition, PackageQueryBuilder, PaginatedResponse, SortDirection},
},
SoarResult,
};
Expand Down Expand Up @@ -113,7 +113,7 @@ pub async fn query_package(query: String) -> SoarResult<()> {
let state = AppState::new().await?;
let repo_db = state.repo_db().clone();

let packages = PackageQueryBuilder::new(repo_db)
let packages: Vec<Package> = PackageQueryBuilder::new(repo_db)
.where_and("pkg_name", FilterCondition::Eq(query))
.load()?
.items;
Expand Down Expand Up @@ -346,6 +346,29 @@ pub async fn query_package(query: String) -> SoarResult<()> {
Ok(())
}

#[derive(Debug, Clone)]
pub struct PackageList {
pkg_id: String,
pkg_name: String,
repo_name: String,
pkg_type: String,
version: String,
version_upstream: Option<String>,
}

impl FromRow for PackageList {
fn from_row(row: &rusqlite::Row) -> rusqlite::Result<Self> {
Ok(PackageList {
pkg_id: row.get("pkg_id")?,
pkg_name: row.get("pkg_name")?,
repo_name: row.get("repo_name")?,
pkg_type: row.get("pkg_type")?,
version: row.get("version")?,
version_upstream: row.get("version_upstream")?,
})
}
}

pub async fn list_packages(repo_name: Option<String>) -> SoarResult<()> {
let state = AppState::new().await?;
let repo_db = state.repo_db().clone();
Expand All @@ -359,10 +382,30 @@ pub async fn list_packages(repo_name: Option<String>) -> SoarResult<()> {
builder = builder.where_and("repo_name", FilterCondition::Eq(repo_name));
}

builder = builder.select(&[
"pkg_id",
"pkg_name",
"pkg_type",
"version",
"version_upstream",
]);

loop {
let packages = builder.load()?;
let packages: PaginatedResponse<PackageList> = builder.load()?;
for package in &packages.items {
let install_state = get_package_install_state(&core_db, &package)?;
let installed_pkgs = PackageQueryBuilder::new(core_db.clone())
.where_and("repo_name", FilterCondition::Eq(package.repo_name.clone()))
.where_and("pkg_id", FilterCondition::Eq(package.pkg_id.clone()))
.where_and("pkg_name", FilterCondition::Eq(package.pkg_name.clone()))
.limit(1)
.load_installed()?
.items;

let install_state = match installed_pkgs {
_ if installed_pkgs.is_empty() => "-",
_ if installed_pkgs.first().unwrap().is_installed => "+",
_ => "?",
};

info!(
pkg_name = package.pkg_name,
Expand Down
9 changes: 6 additions & 3 deletions soar-cli/src/update.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use soar_core::{
config::get_config,
database::packages::{FilterCondition, PackageQueryBuilder},
database::{
models::Package,
packages::{FilterCondition, PackageQueryBuilder},
},
package::{install::InstallTarget, query::PackageQuery},
SoarResult,
};
Expand All @@ -26,7 +29,7 @@ pub async fn update_packages(packages: Option<Vec<String>>) -> SoarResult<()> {
let installed_pkgs = builder.load_installed()?.items;

for pkg in installed_pkgs {
let updated = builder
let updated: Vec<Package> = builder
.clone()
.database(repo_db.clone())
.where_and("version", FilterCondition::Gt(pkg.version.clone()))
Expand All @@ -50,7 +53,7 @@ pub async fn update_packages(packages: Option<Vec<String>>) -> SoarResult<()> {
.items;

for pkg in installed_packages {
let updated = PackageQueryBuilder::new(repo_db.clone())
let updated: Vec<Package> = PackageQueryBuilder::new(repo_db.clone())
.where_and("repo_name", FilterCondition::Eq(pkg.repo_name.clone()))
.where_and("pkg_name", FilterCondition::Eq(pkg.pkg_name.clone()))
.where_and("pkg_id", FilterCondition::Eq(pkg.pkg_id.clone()))
Expand Down
4 changes: 2 additions & 2 deletions soar-cli/src/use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ pub async fn use_alternate_package(name: &str) -> SoarResult<()> {

if let Some(provides) = &selected_package.provides {
for provide in provides {
if let Some(ref target) = provide.target_name {
if let Some(ref target) = provide.target {
let real_path = install_dir.join(provide.name.clone());
let is_symlink = match provide.strategy {
ProvideStrategy::KeepTargetOnly | ProvideStrategy::KeepBoth => true,
Some(ProvideStrategy::KeepTargetOnly) | Some(ProvideStrategy::KeepBoth) => true,
_ => false,
};
if is_symlink {
Expand Down
14 changes: 9 additions & 5 deletions soar-core/src/database/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ pub trait PackageExt {
fn should_create_original_symlink(&self) -> bool;
}

pub trait FromRow: Sized {
fn from_row(row: &rusqlite::Row) -> rusqlite::Result<Self>;
}

#[derive(Debug, Clone)]
pub struct Package {
pub id: u64,
Expand Down Expand Up @@ -76,8 +80,8 @@ pub struct Package {
pub maintainers: Vec<Maintainer>,
}

impl Package {
pub fn from_row(row: &rusqlite::Row) -> rusqlite::Result<Self> {
impl FromRow for Package {
fn from_row(row: &rusqlite::Row) -> rusqlite::Result<Self> {
let parse_json_vec = |idx: &str| -> rusqlite::Result<Option<Vec<String>>> {
Ok(row
.get::<_, Option<String>>(idx)?
Expand Down Expand Up @@ -182,8 +186,8 @@ pub struct InstalledPackage {
pub provides: Option<Vec<PackageProvide>>,
}

impl InstalledPackage {
pub fn from_row(row: &rusqlite::Row) -> rusqlite::Result<Self> {
impl FromRow for InstalledPackage {
fn from_row(row: &rusqlite::Row) -> rusqlite::Result<Self> {
let parse_provides = |idx: &str| -> rusqlite::Result<Option<Vec<PackageProvide>>> {
let value: Option<String> = row.get(idx)?;
Ok(value.and_then(|s| serde_json::from_str(&s).ok()))
Expand Down Expand Up @@ -380,7 +384,7 @@ fn should_create_original_symlink_impl(provides: Option<&Vec<PackageProvide>>) -
.map(|links| {
!links
.iter()
.any(|link| matches!(link.strategy, ProvideStrategy::KeepTargetOnly))
.any(|link| matches!(link.strategy, Some(ProvideStrategy::KeepTargetOnly)))
})
.unwrap_or(true)
}
Expand Down
Loading

0 comments on commit 826f343

Please sign in to comment.