Skip to content

Commit

Permalink
Install a translator to alias ty to type for purl queries
Browse files Browse the repository at this point in the history
This required us to fix the filter logic so that translation occurs
before fetching the field's column metadata.

Signed-off-by: Jim Crossley <[email protected]>
  • Loading branch information
jcrossley3 committed Dec 6, 2024
1 parent bebb706 commit a94fede
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 27 deletions.
29 changes: 15 additions & 14 deletions common/src/db/query/columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ mod tests {

#[test(tokio::test)]
async fn translation() -> Result<(), anyhow::Error> {
let test = |query: Query, expected: &str| {
let stmt = advisory::Entity::find()
let clause = |query: Query| -> Result<String, Error> {
Ok(advisory::Entity::find()
.select_only()
.column(advisory::Column::Id)
.filtering_with(
Expand All @@ -281,6 +281,7 @@ mod tests {
("severity", "<", "low") => Some("score<0"),
("severity", "<", "medium") => Some("score<3"),
("severity", "<", "high") => Some("score<6"),
("painful", "=", "true") => Some("severity>high"),
_ => None,
}
.map(String::from)
Expand All @@ -289,29 +290,29 @@ mod tests {
_ => None,
})
}),
)
.unwrap()
)?
.build(sea_orm::DatabaseBackend::Postgres)
.to_string()
.split("WHERE ")
.last()
.unwrap()
.to_string();
assert_eq!(stmt, expected);
.to_string())
};

test(
q("severity>medium").sort("severity:desc"),
assert_eq!(
clause(q("severity>medium").sort("severity:desc"))?,
r#""advisory"."score" > 6 ORDER BY "advisory"."score" DESC"#,
);
test(
q("severity=medium"),
assert_eq!(
clause(q("severity=medium"))?,
r#""advisory"."score" >= 3 AND "advisory"."score" < 6"#,
);
test(
q("severity=low|high"),
assert_eq!(
clause(q("severity=low|high"))?,
r#"("advisory"."score" >= 0 AND "advisory"."score" < 3) OR ("advisory"."score" >= 6 AND "advisory"."score" < 10)"#,
);
assert_eq!(clause(q("painful=true"))?, r#""advisory"."score" > 10"#);
assert!(clause(q("painful=false")).is_err());

Ok(())
}
Expand Down Expand Up @@ -339,7 +340,7 @@ mod tests {

#[test(tokio::test)]
async fn json_queries() -> Result<(), anyhow::Error> {
fn clause(query: Query) -> Result<String, Error> {
let clause = |query: Query| -> Result<String, Error> {
Ok(advisory::Entity::find()
.filtering_with(
query,
Expand All @@ -353,7 +354,7 @@ mod tests {
.last()
.unwrap()
.to_string())
}
};

assert_eq!(
clause(q("name~log4j&version>1.0"))?,
Expand Down
20 changes: 10 additions & 10 deletions common/src/db/query/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ impl TryFrom<(&str, Operator, &Vec<String>, &Columns)> for Filter {
type Error = Error;
fn try_from(tuple: (&str, Operator, &Vec<String>, &Columns)) -> Result<Self, Self::Error> {
let (field, operator, values, columns) = tuple;
let (expr, col_def) = columns.for_field(field)?;
Ok(Filter {
operator: match operator {
Operator::NotLike | Operator::NotEqual => Operator::And,
Expand All @@ -39,19 +38,20 @@ impl TryFrom<(&str, Operator, &Vec<String>, &Columns)> for Filter {
operands: Operand::Composite(
values
.iter()
.map(|s| Arg::parse(s, col_def.get_column_type()).map(|v| (s, v)))
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flat_map(
|(s, v)| match columns.translate(field, &operator.to_string(), s) {
.map(
|s| match columns.translate(field, &operator.to_string(), s) {
Some(x) => q(&x).filter_for(columns),
None => Ok(Filter {
operands: Operand::Simple(expr.clone(), v),
operator,
None => columns.for_field(field).and_then(|(expr, col_def)| {
Arg::parse(s, col_def.get_column_type()).and_then(|v| {
Ok(Filter {
operands: Operand::Simple(expr.clone(), v),
operator,
})
})
}),
},
)
.collect(),
.collect::<Result<Vec<_>, _>>()?,
),
})
}
Expand Down
4 changes: 2 additions & 2 deletions modules/fundamental/src/purl/endpoints/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ async fn qualified_packages_filtering(ctx: &TrustifyContext) -> Result<(), anyho
setup(&ctx.db, &ctx.graph).await?;
let app = caller(ctx).await?;

let uri = format!("/api/v1/purl?q={}", encode("ty=maven"));
let uri = format!("/api/v1/purl?q={}", encode("type=maven"));
let request = TestRequest::get().uri(&uri).to_request();
let response: PaginatedResults<PurlSummary> = app.call_and_read_body_json(request).await;
assert_eq!(3, response.items.len());
Expand All @@ -304,7 +304,7 @@ async fn qualified_packages_filtering(ctx: &TrustifyContext) -> Result<(), anyho
&ctx.db,
)
.await?;
let uri = format!("/api/v1/purl?q={}", encode("ty=rpm&arch=i386"));
let uri = format!("/api/v1/purl?q={}", encode("type=rpm&arch=i386"));
let request = TestRequest::get().uri(&uri).to_request();
let response: PaginatedResults<PurlSummary> = app.call_and_read_body_json(request).await;
assert_eq!(1, response.items.len());
Expand Down
6 changes: 5 additions & 1 deletion modules/fundamental/src/purl/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,11 @@ impl PurlService {
qualified_purl::Entity
.columns()
.json_keys("purl", &["ty", "namespace", "name", "version"])
.json_keys("qualifiers", &["arch", "type", "repository_url"]),
.json_keys("qualifiers", &["arch", "distro", "repository_url"])
.translator(|f, op, v| match f {
"type" => Some(format!("ty{op}{v}")),
_ => None,
}),
)?
.limiting(connection, paginated.offset, paginated.limit);

Expand Down

0 comments on commit a94fede

Please sign in to comment.