1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! # QueryExecutor - numeric_comparison_group Methods
//!
//! This module contains method implementations for `QueryExecutor`.
//!
//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
use anyhow::Result;
use super::queryexecutor_type::QueryExecutor;
impl QueryExecutor {
/// Perform numeric comparison between terms
pub(super) fn numeric_comparison(
&self,
left: &crate::algebra::Term,
right: &crate::algebra::Term,
op: impl Fn(f64, f64) -> bool,
) -> Result<crate::algebra::Term> {
// Try numeric comparison first
let left_num_result = self.extract_numeric_value(left);
let right_num_result = self.extract_numeric_value(right);
let result = match (left_num_result, right_num_result) {
(Ok(left_num), Ok(right_num)) => op(left_num, right_num),
_ => {
// Fall back to lexicographic string comparison for non-numeric types
// This handles xsd:string, plain literals, etc.
let left_str = match left {
crate::algebra::Term::Literal(lit) => lit.value.clone(),
crate::algebra::Term::Iri(iri) => iri.to_string(),
_ => {
return Err(anyhow::anyhow!(
"Cannot compare non-literal terms: {:?} and {:?}",
left,
right
))
}
};
let right_str = match right {
crate::algebra::Term::Literal(lit) => lit.value.clone(),
crate::algebra::Term::Iri(iri) => iri.to_string(),
_ => {
return Err(anyhow::anyhow!(
"Cannot compare non-literal terms: {:?} and {:?}",
left,
right
))
}
};
// Use string comparison via numeric op approximation:
// Map string ordering to f64: -1.0, 0.0, 1.0
let ordering = left_str.cmp(&right_str);
let left_ord = match ordering {
std::cmp::Ordering::Less => 0.0f64,
std::cmp::Ordering::Equal => 1.0f64,
std::cmp::Ordering::Greater => 2.0f64,
};
// We need to apply op with string ordering semantics
// op(left, right) where left < right: op(0.0, 1.0)
// op(left, right) where left = right: op(1.0, 1.0)
// op(left, right) where left > right: op(2.0, 1.0)
op(left_ord, 1.0)
}
};
Ok(crate::algebra::Term::Literal(crate::algebra::Literal {
value: result.to_string(),
language: None,
datatype: Some(oxirs_core::model::NamedNode::new_unchecked(
"http://www.w3.org/2001/XMLSchema#boolean",
)),
}))
}
/// Extract numeric value from a term
pub(super) fn extract_numeric_value(&self, term: &crate::algebra::Term) -> Result<f64> {
match term {
crate::algebra::Term::Literal(lit) => lit
.value
.parse::<f64>()
.map_err(|_| anyhow::anyhow!("Cannot convert literal to number: {}", lit.value)),
_ => Err(anyhow::anyhow!(
"Cannot extract numeric value from non-literal term"
)),
}
}
}