Pre: add tests for CC constraint intersection.
Also add a failing test for #373.
This commit is contained in:
parent
11a9a30d35
commit
d8d36140a9
1 changed files with 118 additions and 0 deletions
|
@ -821,6 +821,7 @@ impl ConjoiningClauses {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod testing {
|
mod testing {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use mentat_core::attribute::Unique;
|
||||||
use mentat_query::PlainSymbol;
|
use mentat_query::PlainSymbol;
|
||||||
|
|
||||||
fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
||||||
|
@ -1207,6 +1208,8 @@ mod testing {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
/// Bind a value to a variable in a query where the type of the value disagrees with the type of
|
||||||
|
/// the variable inferred from known attributes.
|
||||||
fn test_value_bindings_type_disagreement() {
|
fn test_value_bindings_type_disagreement() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
|
@ -1234,4 +1237,119 @@ mod testing {
|
||||||
// The type of the provided binding doesn't match the type of the attribute.
|
// The type of the provided binding doesn't match the type of the attribute.
|
||||||
assert!(cc.is_known_empty);
|
assert!(cc.is_known_empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
/// Bind a non-textual value to a variable in a query where the variable is used as the value
|
||||||
|
/// of a fulltext-valued attribute.
|
||||||
|
fn test_fulltext_type_disagreement() {
|
||||||
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
|
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
||||||
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
|
value_type: ValueType::String,
|
||||||
|
fulltext: true,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
let x = Variable(PlainSymbol::new("?x"));
|
||||||
|
let y = Variable(PlainSymbol::new("?y"));
|
||||||
|
|
||||||
|
let b: BTreeMap<Variable, TypedValue> =
|
||||||
|
vec![(y.clone(), TypedValue::Long(42))].into_iter().collect();
|
||||||
|
let mut cc = ConjoiningClauses::with_value_bindings(b);
|
||||||
|
|
||||||
|
cc.apply_pattern(&schema, &Pattern {
|
||||||
|
source: None,
|
||||||
|
entity: PatternNonValuePlace::Variable(x.clone()),
|
||||||
|
attribute: PatternNonValuePlace::Ident(NamespacedKeyword::new("foo", "bar")),
|
||||||
|
value: PatternValuePlace::Variable(y.clone()),
|
||||||
|
tx: PatternNonValuePlace::Placeholder,
|
||||||
|
});
|
||||||
|
|
||||||
|
// The type of the provided binding doesn't match the type of the attribute.
|
||||||
|
assert!(cc.is_known_empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
/// Apply two patterns with differently typed attributes, but sharing a variable in the value
|
||||||
|
/// place. No value can bind to a variable and match both types, so the CC is known to return
|
||||||
|
/// no results.
|
||||||
|
fn test_apply_two_conflicting_known_patterns() {
|
||||||
|
let mut cc = ConjoiningClauses::default();
|
||||||
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
|
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
||||||
|
associate_ident(&mut schema, NamespacedKeyword::new("foo", "roz"), 98);
|
||||||
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
|
value_type: ValueType::Boolean,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
add_attribute(&mut schema, 98, Attribute {
|
||||||
|
value_type: ValueType::String,
|
||||||
|
unique: Some(Unique::Identity),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
let x = Variable(PlainSymbol::new("?x"));
|
||||||
|
let y = Variable(PlainSymbol::new("?y"));
|
||||||
|
cc.apply_pattern(&schema, &Pattern {
|
||||||
|
source: None,
|
||||||
|
entity: PatternNonValuePlace::Variable(x.clone()),
|
||||||
|
attribute: PatternNonValuePlace::Ident(NamespacedKeyword::new("foo", "roz")),
|
||||||
|
value: PatternValuePlace::Variable(y.clone()),
|
||||||
|
tx: PatternNonValuePlace::Placeholder,
|
||||||
|
});
|
||||||
|
cc.apply_pattern(&schema, &Pattern {
|
||||||
|
source: None,
|
||||||
|
entity: PatternNonValuePlace::Variable(x.clone()),
|
||||||
|
attribute: PatternNonValuePlace::Ident(NamespacedKeyword::new("foo", "bar")),
|
||||||
|
value: PatternValuePlace::Variable(y.clone()),
|
||||||
|
tx: PatternNonValuePlace::Placeholder,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Finally, expand column bindings to get the overlaps for ?x.
|
||||||
|
cc.expand_column_bindings();
|
||||||
|
|
||||||
|
assert!(cc.is_known_empty);
|
||||||
|
assert_eq!(cc.empty_because.unwrap(),
|
||||||
|
EmptyBecause::TypeMismatch(y.clone(), ValueType::String, ValueType::Boolean));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "assertion failed: cc.is_known_empty")]
|
||||||
|
/// This test needs range inference in order to succeed: we must deduce that ?y must
|
||||||
|
/// simultaneously be a boolean-valued attribute and a ref-valued attribute, and thus
|
||||||
|
/// the CC can never return results.
|
||||||
|
fn test_apply_two_implicitly_conflicting_patterns() {
|
||||||
|
let mut cc = ConjoiningClauses::default();
|
||||||
|
let schema = Schema::default();
|
||||||
|
|
||||||
|
// [:find ?x :where
|
||||||
|
// [?x ?y true]
|
||||||
|
// [?z ?y ?x]]
|
||||||
|
let x = Variable(PlainSymbol::new("?x"));
|
||||||
|
let y = Variable(PlainSymbol::new("?y"));
|
||||||
|
let z = Variable(PlainSymbol::new("?z"));
|
||||||
|
cc.apply_pattern(&schema, &Pattern {
|
||||||
|
source: None,
|
||||||
|
entity: PatternNonValuePlace::Variable(x.clone()),
|
||||||
|
attribute: PatternNonValuePlace::Variable(y.clone()),
|
||||||
|
value: PatternValuePlace::Constant(NonIntegerConstant::Boolean(true)),
|
||||||
|
tx: PatternNonValuePlace::Placeholder,
|
||||||
|
});
|
||||||
|
cc.apply_pattern(&schema, &Pattern {
|
||||||
|
source: None,
|
||||||
|
entity: PatternNonValuePlace::Variable(z.clone()),
|
||||||
|
attribute: PatternNonValuePlace::Variable(y.clone()),
|
||||||
|
value: PatternValuePlace::Variable(x.clone()),
|
||||||
|
tx: PatternNonValuePlace::Placeholder,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Finally, expand column bindings to get the overlaps for ?x.
|
||||||
|
cc.expand_column_bindings();
|
||||||
|
|
||||||
|
assert!(cc.is_known_empty);
|
||||||
|
assert_eq!(cc.empty_because.unwrap(),
|
||||||
|
EmptyBecause::TypeMismatch(x.clone(), ValueType::Ref, ValueType::Boolean));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue