mirror of
https://github.com/martinvonz/jj.git
synced 2024-11-28 17:41:14 +00:00
revset: don't rewrite '~set & filter' as difference
Since filter is slow in general, its input set should be minimized. This has measurable impact on artificial query like '~(v0.4.0..) & author(_)'. If it were evaluated as a difference of sets, all commits would have to be loaded.
This commit is contained in:
parent
707d82245f
commit
0bfdbcaa1e
1 changed files with 64 additions and 8 deletions
|
@ -1380,6 +1380,8 @@ fn fold_difference(expression: &Rc<RevsetExpression>) -> TransformedExpression {
|
||||||
transform_expression_bottom_up(expression, |expression| match expression.as_ref() {
|
transform_expression_bottom_up(expression, |expression| match expression.as_ref() {
|
||||||
RevsetExpression::Intersection(expression1, expression2) => {
|
RevsetExpression::Intersection(expression1, expression2) => {
|
||||||
match (expression1.as_ref(), expression2.as_ref()) {
|
match (expression1.as_ref(), expression2.as_ref()) {
|
||||||
|
// For '~x & f', don't move filter node 'f' left
|
||||||
|
(_, RevsetExpression::Filter(_) | RevsetExpression::AsFilter(_)) => None,
|
||||||
(_, RevsetExpression::NotIn(complement)) => {
|
(_, RevsetExpression::NotIn(complement)) => {
|
||||||
Some(to_difference(expression1, complement))
|
Some(to_difference(expression1, complement))
|
||||||
}
|
}
|
||||||
|
@ -2490,13 +2492,11 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
optimize(parse("present(author(foo) ~ bar)").unwrap()),
|
optimize(parse("present(foo ~ bar)").unwrap()),
|
||||||
Rc::new(RevsetExpression::AsFilter(Rc::new(
|
Rc::new(RevsetExpression::Present(
|
||||||
RevsetExpression::Present(
|
RevsetExpression::symbol("foo".to_owned())
|
||||||
RevsetExpression::filter(RevsetFilterPredicate::Author("foo".to_owned()))
|
.minus(&RevsetExpression::symbol("bar".to_owned()))
|
||||||
.minus(&RevsetExpression::symbol("bar".to_owned()))
|
))
|
||||||
)
|
|
||||||
)))
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
optimize(parse("present(branches() & all())").unwrap()),
|
optimize(parse("present(branches() & all())").unwrap()),
|
||||||
|
@ -2766,7 +2766,63 @@ mod tests {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
"###)
|
"###);
|
||||||
|
|
||||||
|
// '~set & filter()' shouldn't be substituted.
|
||||||
|
insta::assert_debug_snapshot!(
|
||||||
|
optimize(parse("~foo & author(bar)").unwrap()), @r###"
|
||||||
|
Intersection(
|
||||||
|
NotIn(
|
||||||
|
Symbol(
|
||||||
|
"foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Filter(
|
||||||
|
Author(
|
||||||
|
"bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
"###);
|
||||||
|
insta::assert_debug_snapshot!(
|
||||||
|
optimize(parse("~foo & (author(bar) | baz)").unwrap()), @r###"
|
||||||
|
Intersection(
|
||||||
|
NotIn(
|
||||||
|
Symbol(
|
||||||
|
"foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AsFilter(
|
||||||
|
Union(
|
||||||
|
Filter(
|
||||||
|
Author(
|
||||||
|
"bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Symbol(
|
||||||
|
"baz",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
"###);
|
||||||
|
|
||||||
|
// Filter should be moved right of the intersection.
|
||||||
|
insta::assert_debug_snapshot!(
|
||||||
|
optimize(parse("author(foo) ~ bar").unwrap()), @r###"
|
||||||
|
Intersection(
|
||||||
|
NotIn(
|
||||||
|
Symbol(
|
||||||
|
"bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Filter(
|
||||||
|
Author(
|
||||||
|
"foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue