Skip to content

Commit fbe87e4

Browse files
committed
fix bugs with SPARQL sameValue
1 parent 86aa7b8 commit fbe87e4

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

sparql/src/expression.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -495,18 +495,35 @@ impl EvalResult {
495495
}
496496

497497
pub fn sparql_eq(&self, other: &Self) -> Option<bool> {
498-
if let (Some(s), Some(o)) = (self.as_value(), other.as_value()) {
499-
s.sparql_eq(o)
500-
} else {
501-
let s = self.as_term();
502-
let o = other.as_term();
503-
if Term::eq(&s, &o) {
498+
let st = self.as_term();
499+
let ot = other.as_term();
500+
if Term::eq(&st, &ot) {
501+
Some(true)
502+
} else if st.is_iri()
503+
|| st.is_blank_node()
504+
|| ot.is_iri()
505+
|| ot.is_blank_node()
506+
|| (st.is_triple() && !ot.is_triple() || !st.is_triple() && ot.is_triple())
507+
{
508+
Some(false)
509+
} else if let Some(stt) = st.triple()
510+
&& let Some(ott) = ot.triple()
511+
{
512+
let [s1, p1, o1] = stt.map(|t| EvalResult::Term(t.clone().into()));
513+
let [s2, p2, o2] = ott.map(|t| EvalResult::Term(t.clone().into()));
514+
Some(s1.sparql_eq(&s2)? && p1.sparql_eq(&p2)? && o1.sparql_eq(&o2)?)
515+
} else if let Some(sv) = self.as_value()
516+
&& let Some(ov) = other.as_value()
517+
{
518+
if sv.is_ill_formed() || ov.is_ill_formed() {
519+
None
520+
} else if sv.is_nan() && ov.is_nan() {
504521
Some(true)
505-
} else if s.is_literal() && o.is_literal() {
506-
None // distinct unrecognized literals can not be compared
507522
} else {
508-
Some(false)
523+
sv.sparql_eq(ov)
509524
}
525+
} else {
526+
None
510527
}
511528
}
512529

sparql/src/test.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1902,6 +1902,7 @@ fn test_expr(expr: &str, result: &str) -> TestResult {
19021902
#[test_case("42", "42e0", Some(true))]
19031903
#[test_case("42.0", "42e0", Some(true))]
19041904
#[test_case("42", "43", Some(false))]
1905+
#[test_case("\"foo\"^^xsd:integer", "42", None)]
19051906
#[test_case("\"a\"", "\"\"", Some(false))]
19061907
#[test_case("\"a\"@en", "\"\"@en", Some(false))]
19071908
#[test_case("\"a\"@en", "\"a\"@fr", Some(false))]
@@ -1949,7 +1950,7 @@ fn test_expr_eq(expr1: &str, expr2: &str, exp: Option<bool>) -> TestResult {
19491950
assert_eq!(eval_expr(&format!("{expr2} = {expr2}"))?, TRUE);
19501951
assert_eq!(eval_expr(&format!("{expr2} != {expr2}"))?, FALSE);
19511952
// control: every recognized value is equal to itself via comparison operators
1952-
if !expr1.contains("<tag:") {
1953+
if !expr1.contains("<tag:") && !expr1.contains("\"foo\"") {
19531954
assert_eq!(eval_expr(&format!("{expr1} <= {expr1}"))?, TRUE);
19541955
assert_eq!(eval_expr(&format!("{expr1} >= {expr1}"))?, TRUE);
19551956
assert_eq!(eval_expr(&format!("{expr1} < {expr1}"))?, FALSE);

sparql/src/value.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ impl SparqlValue {
113113
}
114114
}
115115

116+
pub fn is_nan(&self) -> bool {
117+
match self {
118+
SparqlValue::Number(Some(SparqlNumber::Float(f))) => f.is_nan(),
119+
SparqlValue::Number(Some(SparqlNumber::Double(d))) => d.is_nan(),
120+
_ => false,
121+
}
122+
}
123+
116124
pub fn sparql_eq(&self, other: &Self) -> Option<bool> {
117125
use SparqlValue::*;
118126
match (self, other) {
@@ -121,9 +129,9 @@ impl SparqlValue {
121129
d1.partial_cmp(d2).map(|o| o == Ordering::Equal)
122130
}
123131
(Number(Some(n1)), Number(Some(n2))) => Some(n1 == n2),
124-
(String(s1, None), String(s2, None)) => Some(s1 == s2),
125-
(String(s1, Some(t1)), String(s2, Some(t2))) => Some(t1 == t2 && s1 == s2),
126-
_ => None,
132+
(String(s1, opt1), String(s2, opt2)) => Some(s1 == s2 && opt1 == opt2),
133+
_ if self.is_ill_formed() || other.is_ill_formed() => None,
134+
_ => Some(false),
127135
}
128136
}
129137

typos.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extend-ignore-identifiers-re = [
66
# I prefer this to 'type_'
77
"typ",
88
"iz",
9+
"ot",
910
]
1011
extend-ignore-re = [
1112
"raison d'être",

0 commit comments

Comments
 (0)