diff --git a/migration/src/lib.rs b/migration/src/lib.rs index bc28326f..9b6debc8 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -91,6 +91,7 @@ mod m0000700_advisory_add_reserved; mod m0000710_create_user_prefs; mod m0000720_alter_sbom_fix_null_array; mod m0000730_alter_importer_add_progress; +mod m0000740_ensure_get_purl_fns; pub struct Migrator; @@ -189,6 +190,7 @@ impl MigratorTrait for Migrator { Box::new(m0000710_create_user_prefs::Migration), Box::new(m0000720_alter_sbom_fix_null_array::Migration), Box::new(m0000730_alter_importer_add_progress::Migration), + Box::new(m0000740_ensure_get_purl_fns::Migration), ] } } diff --git a/migration/src/m0000740_ensure_get_purl_fns.rs b/migration/src/m0000740_ensure_get_purl_fns.rs new file mode 100644 index 00000000..878cc9b9 --- /dev/null +++ b/migration/src/m0000740_ensure_get_purl_fns.rs @@ -0,0 +1,26 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("m0000740_ensure_get_purl_fns/get_purl.sql")) + .await + .map(|_| ())?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("m0000590_get_purl_fns/get_purl.sql")) + .await?; + + Ok(()) + } +} diff --git a/migration/src/m0000740_ensure_get_purl_fns/get_purl.sql b/migration/src/m0000740_ensure_get_purl_fns/get_purl.sql new file mode 100644 index 00000000..7f6ae26a --- /dev/null +++ b/migration/src/m0000740_ensure_get_purl_fns/get_purl.sql @@ -0,0 +1,33 @@ +CREATE OR REPLACE FUNCTION get_purl(qualified_purl_id UUID) +RETURNS TEXT AS $$ +DECLARE +result TEXT; +BEGIN +SELECT + COALESCE( + 'pkg:' || bp.type || + '/' || COALESCE(bp.namespace, '') || '/' || + bp.name || + '@' || vp.version || + CASE + WHEN qp.qualifiers IS NOT NULL AND qp.qualifiers <> '{}'::jsonb THEN + '?' || ( + SELECT string_agg(key || '=' || value, '&') + FROM jsonb_each_text(qp.qualifiers) + ) + ELSE + '' + END, + qualified_purl_id::text + ) +INTO result +FROM + qualified_purl qp + LEFT JOIN versioned_purl vp ON vp.id = qp.versioned_purl_id + LEFT JOIN base_purl bp ON bp.id = vp.base_purl_id +WHERE + qp.id = qualified_purl_id; + +RETURN result; +END; +$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE; \ No newline at end of file diff --git a/modules/analysis/src/service.rs b/modules/analysis/src/service.rs index a657bb5f..306500b8 100644 --- a/modules/analysis/src/service.rs +++ b/modules/analysis/src/service.rs @@ -36,9 +36,9 @@ pub struct AnalysisService { pub fn dep_nodes( graph: &petgraph::Graph, node: NodeIndex, + visited: &mut HashSet, ) -> Vec { let mut depnodes = Vec::new(); - let mut visited = HashSet::new(); fn dfs( graph: &petgraph::Graph, node: NodeIndex, @@ -57,7 +57,7 @@ pub fn dep_nodes( purl: dep_packagenode.purl.to_string(), name: dep_packagenode.name.to_string(), version: dep_packagenode.version.to_string(), - deps: Vec::new(), // Avoid recursive call to dep_nodes + deps: dep_nodes(graph, neighbor, visited), }; depnodes.push(dep_node); dfs(graph, neighbor, depnodes, visited); @@ -69,7 +69,7 @@ pub fn dep_nodes( } } } - dfs(graph, node, &mut depnodes, &mut visited); + dfs(graph, node, &mut depnodes, visited); depnodes } @@ -530,7 +530,7 @@ impl AnalysisService { product_version: find_match_package_node .product_version .to_string(), - deps: dep_nodes(graph, node_index), + deps: dep_nodes(graph, node_index, &mut HashSet::new()), }); } }