Part 5: add more tests for complex or
.
This commit is contained in:
parent
bca8b7e322
commit
758ab8b476
1 changed files with 44 additions and 13 deletions
|
@ -710,13 +710,23 @@ mod testing {
|
||||||
SourceAlias,
|
SourceAlias,
|
||||||
};
|
};
|
||||||
|
|
||||||
use algebrize;
|
use {
|
||||||
|
algebrize,
|
||||||
|
algebrize_with_counter,
|
||||||
|
};
|
||||||
|
|
||||||
fn alg(schema: &Schema, input: &str) -> ConjoiningClauses {
|
fn alg(schema: &Schema, input: &str) -> ConjoiningClauses {
|
||||||
let parsed = parse_find_string(input).expect("parse failed");
|
let parsed = parse_find_string(input).expect("parse failed");
|
||||||
algebrize(schema.into(), parsed).expect("algebrize failed").cc
|
algebrize(schema.into(), parsed).expect("algebrize failed").cc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Algebrize with a starting counter, so we can compare inner queries by algebrizing a
|
||||||
|
/// simpler version.
|
||||||
|
fn alg_c(schema: &Schema, counter: usize, input: &str) -> ConjoiningClauses {
|
||||||
|
let parsed = parse_find_string(input).expect("parse failed");
|
||||||
|
algebrize_with_counter(schema.into(), parsed, counter).expect("algebrize failed").cc
|
||||||
|
}
|
||||||
|
|
||||||
fn compare_ccs(left: ConjoiningClauses, right: ConjoiningClauses) {
|
fn compare_ccs(left: ConjoiningClauses, right: ConjoiningClauses) {
|
||||||
assert_eq!(left.wheres, right.wheres);
|
assert_eq!(left.wheres, right.wheres);
|
||||||
assert_eq!(left.from, right.from);
|
assert_eq!(left.from, right.from);
|
||||||
|
@ -927,8 +937,6 @@ mod testing {
|
||||||
// These two are not equivalent:
|
// These two are not equivalent:
|
||||||
// [:find ?x :where [?x :foo/bar ?y] (or-join [?x] [?x :foo/baz ?y])]
|
// [:find ?x :where [?x :foo/bar ?y] (or-join [?x] [?x :foo/baz ?y])]
|
||||||
// [:find ?x :where [?x :foo/bar ?y] [?x :foo/baz ?y]]
|
// [:find ?x :where [?x :foo/bar ?y] [?x :foo/baz ?y]]
|
||||||
// TODO: fixme
|
|
||||||
/*
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unit_or_join_doesnt_flatten() {
|
fn test_unit_or_join_doesnt_flatten() {
|
||||||
let schema = prepopulated_schema();
|
let schema = prepopulated_schema();
|
||||||
|
@ -939,30 +947,27 @@ mod testing {
|
||||||
let vx = Variable::from_valid_name("?x");
|
let vx = Variable::from_valid_name("?x");
|
||||||
let vy = Variable::from_valid_name("?y");
|
let vy = Variable::from_valid_name("?y");
|
||||||
let d0 = "datoms00".to_string();
|
let d0 = "datoms00".to_string();
|
||||||
let d1 = "datoms01".to_string();
|
let c0 = "c00".to_string();
|
||||||
|
let c0x = QualifiedAlias::new(c0.clone(), VariableColumn::Variable(vx.clone()));
|
||||||
let d0e = QualifiedAlias::new(d0.clone(), DatomsColumn::Entity);
|
let d0e = QualifiedAlias::new(d0.clone(), DatomsColumn::Entity);
|
||||||
let d0a = QualifiedAlias::new(d0.clone(), DatomsColumn::Attribute);
|
let d0a = QualifiedAlias::new(d0.clone(), DatomsColumn::Attribute);
|
||||||
let d0v = QualifiedAlias::new(d0.clone(), DatomsColumn::Value);
|
let d0v = QualifiedAlias::new(d0.clone(), DatomsColumn::Value);
|
||||||
let d1e = QualifiedAlias::new(d1.clone(), DatomsColumn::Entity);
|
|
||||||
let d1a = QualifiedAlias::new(d1.clone(), DatomsColumn::Attribute);
|
|
||||||
let knows = QueryValue::Entid(66);
|
let knows = QueryValue::Entid(66);
|
||||||
let parent = QueryValue::Entid(67);
|
|
||||||
|
|
||||||
assert!(!cc.is_known_empty());
|
assert!(!cc.is_known_empty());
|
||||||
assert_eq!(cc.wheres, ColumnIntersection(vec![
|
assert_eq!(cc.wheres, ColumnIntersection(vec![
|
||||||
ColumnConstraintOrAlternation::Constraint(ColumnConstraint::Equals(d0a.clone(), knows.clone())),
|
ColumnConstraintOrAlternation::Constraint(ColumnConstraint::Equals(d0a.clone(), knows.clone())),
|
||||||
// The outer pattern joins against the `or` on the entity, but not value -- ?y means
|
// The outer pattern joins against the `or` on the entity, but not value -- ?y means
|
||||||
// different things in each place.
|
// different things in each place.
|
||||||
ColumnConstraintOrAlternation::Constraint(ColumnConstraint::Equals(d0e.clone(), QueryValue::Column(QualifiedAlias::new("c00".to_string(), VariableColumn::Variable(vx.clone()))))),
|
ColumnConstraintOrAlternation::Constraint(ColumnConstraint::Equals(d0e.clone(), QueryValue::Column(c0x.clone()))),
|
||||||
]));
|
]));
|
||||||
assert_eq!(cc.column_bindings.get(&vx), Some(&vec![d0e, d1e]));
|
assert_eq!(cc.column_bindings.get(&vx), Some(&vec![d0e, c0x]));
|
||||||
|
|
||||||
// ?y does not have a binding in the `or-join` pattern.
|
// ?y does not have a binding in the `or-join` pattern.
|
||||||
assert_eq!(cc.column_bindings.get(&vy), Some(&vec![d0v]));
|
assert_eq!(cc.column_bindings.get(&vy), Some(&vec![d0v]));
|
||||||
assert_eq!(cc.from, vec![SourceAlias(DatomsTable::Datoms, d0),
|
assert_eq!(cc.from, vec![SourceAlias(DatomsTable::Datoms, d0),
|
||||||
SourceAlias(DatomsTable::Datoms, d1)]);
|
SourceAlias(DatomsTable::Computed(0), c0)]);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// These two are equivalent:
|
// These two are equivalent:
|
||||||
// [:find ?x :where [?x :foo/bar ?y] (or [?x :foo/baz ?y])]
|
// [:find ?x :where [?x :foo/bar ?y] (or [?x :foo/baz ?y])]
|
||||||
|
@ -1002,8 +1007,6 @@ mod testing {
|
||||||
/// Strictly speaking this can be implemented with a `NOT EXISTS` clause for the second pattern,
|
/// Strictly speaking this can be implemented with a `NOT EXISTS` clause for the second pattern,
|
||||||
/// but that would be a fair amount of analysis work, I think.
|
/// but that would be a fair amount of analysis work, I think.
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(dead_code, unused_variables)]
|
|
||||||
// TODO: flesh this out.
|
|
||||||
fn test_alternation_with_and() {
|
fn test_alternation_with_and() {
|
||||||
let schema = prepopulated_schema();
|
let schema = prepopulated_schema();
|
||||||
let query = r#"
|
let query = r#"
|
||||||
|
@ -1012,6 +1015,34 @@ mod testing {
|
||||||
[?x :foo/parent "Ámbar"])
|
[?x :foo/parent "Ámbar"])
|
||||||
[?x :foo/knows "Daphne"])]"#;
|
[?x :foo/knows "Daphne"])]"#;
|
||||||
let cc = alg(&schema, query);
|
let cc = alg(&schema, query);
|
||||||
|
let mut tables = cc.computed_tables.into_iter();
|
||||||
|
match (tables.next(), tables.next()) {
|
||||||
|
(Some(ComputedTable::Union { projection, type_extraction, arms }), None) => {
|
||||||
|
assert_eq!(projection, vec![Variable::from_valid_name("?x")].into_iter().collect());
|
||||||
|
assert!(type_extraction.is_empty());
|
||||||
|
|
||||||
|
let mut arms = arms.into_iter();
|
||||||
|
match (arms.next(), arms.next(), arms.next()) {
|
||||||
|
(Some(and), Some(pattern), None) => {
|
||||||
|
let expected_and = alg_c(&schema,
|
||||||
|
0, // The first pattern to be processed.
|
||||||
|
r#"[:find ?x :where [?x :foo/knows "John"] [?x :foo/parent "Ámbar"]]"#);
|
||||||
|
compare_ccs(and, expected_and);
|
||||||
|
|
||||||
|
let expected_pattern = alg_c(&schema,
|
||||||
|
2, // Two aliases taken by the other arm.
|
||||||
|
r#"[:find ?x :where [?x :foo/knows "Daphne"]]"#);
|
||||||
|
compare_ccs(pattern, expected_pattern);
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
panic!("Expected two arms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
panic!("Didn't get two inner tables.");
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue