|
|
|
@ -1,6 +1,7 @@ |
|
|
|
|
use crate::model::BlankNode; |
|
|
|
|
use crate::model::Triple; |
|
|
|
|
use crate::sparql::model::*; |
|
|
|
|
use crate::sparql::QueryOptions; |
|
|
|
|
use crate::sparql::plan::*; |
|
|
|
|
use crate::store::numeric_encoder::*; |
|
|
|
|
use crate::store::StoreConnection; |
|
|
|
@ -58,21 +59,26 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
&'b self, |
|
|
|
|
plan: &'b PlanNode, |
|
|
|
|
variables: &[Variable], |
|
|
|
|
options: &'b QueryOptions<'b> |
|
|
|
|
) -> Result<QueryResult<'b>> |
|
|
|
|
where |
|
|
|
|
'a: 'b, |
|
|
|
|
{ |
|
|
|
|
let iter = self.eval_plan(plan, vec![None; variables.len()]); |
|
|
|
|
let iter = self.eval_plan(plan, vec![None; variables.len()], &options); |
|
|
|
|
Ok(QueryResult::Bindings( |
|
|
|
|
self.decode_bindings(iter, variables.to_vec()), |
|
|
|
|
)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn evaluate_ask_plan<'b>(&'b self, plan: &'b PlanNode) -> Result<QueryResult<'b>> |
|
|
|
|
pub fn evaluate_ask_plan<'b>( |
|
|
|
|
&'b self, |
|
|
|
|
plan: &'b PlanNode, |
|
|
|
|
options: &'b QueryOptions<'b> |
|
|
|
|
) -> Result<QueryResult<'b>> |
|
|
|
|
where |
|
|
|
|
'a: 'b, |
|
|
|
|
{ |
|
|
|
|
match self.eval_plan(plan, vec![]).next() { |
|
|
|
|
match self.eval_plan(plan, vec![], &options).next() { |
|
|
|
|
Some(Ok(_)) => Ok(QueryResult::Boolean(true)), |
|
|
|
|
Some(Err(error)) => Err(error), |
|
|
|
|
None => Ok(QueryResult::Boolean(false)), |
|
|
|
@ -83,31 +89,41 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
&'b self, |
|
|
|
|
plan: &'b PlanNode, |
|
|
|
|
construct: &'b [TripleTemplate], |
|
|
|
|
options: &'b QueryOptions<'b> |
|
|
|
|
) -> Result<QueryResult<'b>> |
|
|
|
|
where |
|
|
|
|
'a: 'b, |
|
|
|
|
{ |
|
|
|
|
Ok(QueryResult::Graph(Box::new(ConstructIterator { |
|
|
|
|
eval: self, |
|
|
|
|
iter: self.eval_plan(plan, vec![]), |
|
|
|
|
iter: self.eval_plan(plan, vec![], options), |
|
|
|
|
template: construct, |
|
|
|
|
buffered_results: Vec::default(), |
|
|
|
|
bnodes: Vec::default(), |
|
|
|
|
}))) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn evaluate_describe_plan<'b>(&'b self, plan: &'b PlanNode) -> Result<QueryResult<'b>> |
|
|
|
|
pub fn evaluate_describe_plan<'b>( |
|
|
|
|
&'b self, |
|
|
|
|
plan: &'b PlanNode, |
|
|
|
|
options: &'b QueryOptions<'b> |
|
|
|
|
) -> Result<QueryResult<'b>> |
|
|
|
|
where |
|
|
|
|
'a: 'b, |
|
|
|
|
{ |
|
|
|
|
Ok(QueryResult::Graph(Box::new(DescribeIterator { |
|
|
|
|
eval: self, |
|
|
|
|
iter: self.eval_plan(plan, vec![]), |
|
|
|
|
iter: self.eval_plan(plan, vec![], options), |
|
|
|
|
quads: Box::new(empty()), |
|
|
|
|
}))) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn eval_plan<'b>(&'b self, node: &'b PlanNode, from: EncodedTuple) -> EncodedTuplesIterator<'b> |
|
|
|
|
fn eval_plan<'b>( |
|
|
|
|
&'b self, |
|
|
|
|
node: &'b PlanNode, |
|
|
|
|
from: EncodedTuple, |
|
|
|
|
options: &'b QueryOptions<'b> |
|
|
|
|
) -> EncodedTuplesIterator<'b> |
|
|
|
|
where |
|
|
|
|
'a: 'b, |
|
|
|
|
{ |
|
|
|
@ -120,7 +136,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
predicate, |
|
|
|
|
object, |
|
|
|
|
graph_name, |
|
|
|
|
} => Box::new(self.eval_plan(&*child, from).flat_map_ok(move |tuple| { |
|
|
|
|
} => Box::new(self.eval_plan(&*child, from, options).flat_map_ok(move |tuple| { |
|
|
|
|
let mut iter = self.dataset.quads_for_pattern( |
|
|
|
|
get_pattern_value(&subject, &tuple), |
|
|
|
|
get_pattern_value(&predicate, &tuple), |
|
|
|
@ -186,7 +202,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
path, |
|
|
|
|
object, |
|
|
|
|
graph_name, |
|
|
|
|
} => Box::new(self.eval_plan(&*child, from).flat_map_ok(move |tuple| { |
|
|
|
|
} => Box::new(self.eval_plan(&*child, from, options).flat_map_ok(move |tuple| { |
|
|
|
|
let input_subject = get_pattern_value(&subject, &tuple); |
|
|
|
|
let input_object = get_pattern_value(&object, &tuple); |
|
|
|
|
let input_graph_name = |
|
|
|
@ -244,7 +260,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
//TODO: very dumb implementation
|
|
|
|
|
let mut errors = Vec::default(); |
|
|
|
|
let left_values = self |
|
|
|
|
.eval_plan(&*left, from.clone()) |
|
|
|
|
.eval_plan(&*left, from.clone(), options) |
|
|
|
|
.filter_map(|result| match result { |
|
|
|
|
Ok(result) => Some(result), |
|
|
|
|
Err(error) => { |
|
|
|
@ -255,18 +271,18 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
.collect::<Vec<_>>(); |
|
|
|
|
Box::new(JoinIterator { |
|
|
|
|
left: left_values, |
|
|
|
|
right_iter: self.eval_plan(&*right, from), |
|
|
|
|
right_iter: self.eval_plan(&*right, from, options), |
|
|
|
|
buffered_results: errors, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
PlanNode::AntiJoin { left, right } => { |
|
|
|
|
//TODO: dumb implementation
|
|
|
|
|
let right: Vec<_> = self |
|
|
|
|
.eval_plan(&*right, from.clone()) |
|
|
|
|
.eval_plan(&*right, from.clone(), options) |
|
|
|
|
.filter_map(|result| result.ok()) |
|
|
|
|
.collect(); |
|
|
|
|
Box::new(AntiJoinIterator { |
|
|
|
|
left_iter: self.eval_plan(&*left, from), |
|
|
|
|
left_iter: self.eval_plan(&*left, from, options), |
|
|
|
|
right, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
@ -281,8 +297,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
let iter = LeftJoinIterator { |
|
|
|
|
eval: self, |
|
|
|
|
right_plan: &*right, |
|
|
|
|
left_iter: self.eval_plan(&*left, filtered_from), |
|
|
|
|
left_iter: self.eval_plan(&*left, filtered_from, options), |
|
|
|
|
current_right: Box::new(empty()), |
|
|
|
|
options, |
|
|
|
|
}; |
|
|
|
|
if problem_vars.is_empty() { |
|
|
|
|
Box::new(iter) |
|
|
|
@ -296,10 +313,10 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
PlanNode::Filter { child, expression } => { |
|
|
|
|
let eval = self; |
|
|
|
|
Box::new(self.eval_plan(&*child, from).filter(move |tuple| { |
|
|
|
|
Box::new(self.eval_plan(&*child, from, options).filter(move |tuple| { |
|
|
|
|
match tuple { |
|
|
|
|
Ok(tuple) => eval |
|
|
|
|
.eval_expression(&expression, tuple) |
|
|
|
|
.eval_expression(&expression, tuple, options) |
|
|
|
|
.and_then(|term| eval.to_bool(term)) |
|
|
|
|
.unwrap_or(false), |
|
|
|
|
Err(_) => true, |
|
|
|
@ -312,6 +329,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
input: from, |
|
|
|
|
current_iterator: Box::new(empty()), |
|
|
|
|
current_plan: 0, |
|
|
|
|
options, |
|
|
|
|
}), |
|
|
|
|
PlanNode::Extend { |
|
|
|
|
child, |
|
|
|
@ -319,9 +337,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
expression, |
|
|
|
|
} => { |
|
|
|
|
let eval = self; |
|
|
|
|
Box::new(self.eval_plan(&*child, from).map(move |tuple| { |
|
|
|
|
Box::new(self.eval_plan(&*child, from, options).map(move |tuple| { |
|
|
|
|
let mut tuple = tuple?; |
|
|
|
|
if let Some(value) = eval.eval_expression(&expression, &tuple) { |
|
|
|
|
if let Some(value) = eval.eval_expression(&expression, &tuple, options) { |
|
|
|
|
put_value(*position, value, &mut tuple) |
|
|
|
|
} |
|
|
|
|
Ok(tuple) |
|
|
|
@ -330,7 +348,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
PlanNode::Sort { child, by } => { |
|
|
|
|
let mut errors = Vec::default(); |
|
|
|
|
let mut values = self |
|
|
|
|
.eval_plan(&*child, from) |
|
|
|
|
.eval_plan(&*child, from, options) |
|
|
|
|
.filter_map(|result| match result { |
|
|
|
|
Ok(result) => Some(result), |
|
|
|
|
Err(error) => { |
|
|
|
@ -343,14 +361,14 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
for comp in by { |
|
|
|
|
match comp { |
|
|
|
|
Comparator::Asc(expression) => { |
|
|
|
|
match self.cmp_according_to_expression(a, b, &expression) { |
|
|
|
|
match self.cmp_according_to_expression(a, b, &expression, options) { |
|
|
|
|
Ordering::Greater => return Ordering::Greater, |
|
|
|
|
Ordering::Less => return Ordering::Less, |
|
|
|
|
Ordering::Equal => (), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Comparator::Desc(expression) => { |
|
|
|
|
match self.cmp_according_to_expression(a, b, &expression) { |
|
|
|
|
match self.cmp_according_to_expression(a, b, &expression, options) { |
|
|
|
|
Ordering::Greater => return Ordering::Less, |
|
|
|
|
Ordering::Less => return Ordering::Greater, |
|
|
|
|
Ordering::Equal => (), |
|
|
|
@ -363,16 +381,16 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
Box::new(errors.into_iter().chain(values.into_iter().map(Ok))) |
|
|
|
|
} |
|
|
|
|
PlanNode::HashDeduplicate { child } => { |
|
|
|
|
Box::new(hash_deduplicate(self.eval_plan(&*child, from))) |
|
|
|
|
Box::new(hash_deduplicate(self.eval_plan(&*child, from, options))) |
|
|
|
|
} |
|
|
|
|
PlanNode::Skip { child, count } => Box::new(self.eval_plan(&*child, from).skip(*count)), |
|
|
|
|
PlanNode::Skip { child, count } => Box::new(self.eval_plan(&*child, from, options).skip(*count)), |
|
|
|
|
PlanNode::Limit { child, count } => { |
|
|
|
|
Box::new(self.eval_plan(&*child, from).take(*count)) |
|
|
|
|
Box::new(self.eval_plan(&*child, from, options).take(*count)) |
|
|
|
|
} |
|
|
|
|
PlanNode::Project { child, mapping } => { |
|
|
|
|
//TODO: use from somewhere?
|
|
|
|
|
Box::new( |
|
|
|
|
self.eval_plan(&*child, vec![None; mapping.len()]) |
|
|
|
|
self.eval_plan(&*child, vec![None; mapping.len()], options) |
|
|
|
|
.map(move |tuple| { |
|
|
|
|
let tuple = tuple?; |
|
|
|
|
let mut output_tuple = vec![None; from.len()]; |
|
|
|
@ -394,7 +412,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
let mut errors = Vec::default(); |
|
|
|
|
let mut accumulators_for_group = |
|
|
|
|
HashMap::<Vec<Option<EncodedTerm>>, Vec<Box<dyn Accumulator>>>::default(); |
|
|
|
|
self.eval_plan(child, from) |
|
|
|
|
self.eval_plan(child, from, options) |
|
|
|
|
.filter_map(|result| match result { |
|
|
|
|
Ok(result) => Some(result), |
|
|
|
|
Err(error) => { |
|
|
|
@ -426,7 +444,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
aggregate |
|
|
|
|
.parameter |
|
|
|
|
.as_ref() |
|
|
|
|
.and_then(|parameter| self.eval_expression(¶meter, &tuple)), |
|
|
|
|
.and_then(|parameter| self.eval_expression(¶meter, &tuple, options)), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
@ -666,24 +684,25 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
.map(|e| e.map(|e| (e, e))) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn eval_expression( |
|
|
|
|
&self, |
|
|
|
|
fn eval_expression<'b>( |
|
|
|
|
&'b self, |
|
|
|
|
expression: &PlanExpression, |
|
|
|
|
tuple: &[Option<EncodedTerm>], |
|
|
|
|
options: &QueryOptions<'b> |
|
|
|
|
) -> Option<EncodedTerm> { |
|
|
|
|
match expression { |
|
|
|
|
PlanExpression::Constant(t) => Some(*t), |
|
|
|
|
PlanExpression::Variable(v) => get_tuple_value(*v, tuple), |
|
|
|
|
PlanExpression::Exists(node) => { |
|
|
|
|
Some(self.eval_plan(node, tuple.to_vec()).next().is_some().into()) |
|
|
|
|
Some(self.eval_plan(node, tuple.to_vec(), options).next().is_some().into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::Or(a, b) => { |
|
|
|
|
match self.eval_expression(a, tuple).and_then(|v| self.to_bool(v)) { |
|
|
|
|
match self.eval_expression(a, tuple, options).and_then(|v| self.to_bool(v)) { |
|
|
|
|
Some(true) => Some(true.into()), |
|
|
|
|
Some(false) => self.eval_expression(b, tuple), |
|
|
|
|
Some(false) => self.eval_expression(b, tuple, options), |
|
|
|
|
None => { |
|
|
|
|
if Some(true) |
|
|
|
|
== self.eval_expression(b, tuple).and_then(|v| self.to_bool(v)) |
|
|
|
|
== self.eval_expression(b, tuple, options).and_then(|v| self.to_bool(v)) |
|
|
|
|
{ |
|
|
|
|
Some(true.into()) |
|
|
|
|
} else { |
|
|
|
@ -693,13 +712,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
PlanExpression::And(a, b) => match self |
|
|
|
|
.eval_expression(a, tuple) |
|
|
|
|
.eval_expression(a, tuple, options) |
|
|
|
|
.and_then(|v| self.to_bool(v)) |
|
|
|
|
{ |
|
|
|
|
Some(true) => self.eval_expression(b, tuple), |
|
|
|
|
Some(true) => self.eval_expression(b, tuple, options), |
|
|
|
|
Some(false) => Some(false.into()), |
|
|
|
|
None => { |
|
|
|
|
if Some(false) == self.eval_expression(b, tuple).and_then(|v| self.to_bool(v)) { |
|
|
|
|
if Some(false) == self.eval_expression(b, tuple, options).and_then(|v| self.to_bool(v)) { |
|
|
|
|
Some(false.into()) |
|
|
|
|
} else { |
|
|
|
|
None |
|
|
|
@ -707,26 +726,26 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Equal(a, b) => { |
|
|
|
|
let a = self.eval_expression(a, tuple)?; |
|
|
|
|
let b = self.eval_expression(b, tuple)?; |
|
|
|
|
let a = self.eval_expression(a, tuple, options)?; |
|
|
|
|
let b = self.eval_expression(b, tuple, options)?; |
|
|
|
|
self.equals(a, b).map(|v| v.into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::NotEqual(a, b) => { |
|
|
|
|
let a = self.eval_expression(a, tuple)?; |
|
|
|
|
let b = self.eval_expression(b, tuple)?; |
|
|
|
|
let a = self.eval_expression(a, tuple, options)?; |
|
|
|
|
let b = self.eval_expression(b, tuple, options)?; |
|
|
|
|
self.equals(a, b).map(|v| (!v).into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::Greater(a, b) => Some( |
|
|
|
|
(self.partial_cmp_literals( |
|
|
|
|
self.eval_expression(a, tuple)?, |
|
|
|
|
self.eval_expression(b, tuple)?, |
|
|
|
|
self.eval_expression(a, tuple, options)?, |
|
|
|
|
self.eval_expression(b, tuple, options)?, |
|
|
|
|
)? == Ordering::Greater) |
|
|
|
|
.into(), |
|
|
|
|
), |
|
|
|
|
PlanExpression::GreaterOrEq(a, b) => Some( |
|
|
|
|
match self.partial_cmp_literals( |
|
|
|
|
self.eval_expression(a, tuple)?, |
|
|
|
|
self.eval_expression(b, tuple)?, |
|
|
|
|
self.eval_expression(a, tuple, options)?, |
|
|
|
|
self.eval_expression(b, tuple, options)?, |
|
|
|
|
)? { |
|
|
|
|
Ordering::Greater | Ordering::Equal => true, |
|
|
|
|
Ordering::Less => false, |
|
|
|
@ -735,15 +754,15 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
), |
|
|
|
|
PlanExpression::Lower(a, b) => Some( |
|
|
|
|
(self.partial_cmp_literals( |
|
|
|
|
self.eval_expression(a, tuple)?, |
|
|
|
|
self.eval_expression(b, tuple)?, |
|
|
|
|
self.eval_expression(a, tuple, options)?, |
|
|
|
|
self.eval_expression(b, tuple, options)?, |
|
|
|
|
)? == Ordering::Less) |
|
|
|
|
.into(), |
|
|
|
|
), |
|
|
|
|
PlanExpression::LowerOrEq(a, b) => Some( |
|
|
|
|
match self.partial_cmp_literals( |
|
|
|
|
self.eval_expression(a, tuple)?, |
|
|
|
|
self.eval_expression(b, tuple)?, |
|
|
|
|
self.eval_expression(a, tuple, options)?, |
|
|
|
|
self.eval_expression(b, tuple, options)?, |
|
|
|
|
)? { |
|
|
|
|
Ordering::Less | Ordering::Equal => true, |
|
|
|
|
Ordering::Greater => false, |
|
|
|
@ -751,10 +770,10 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
.into(), |
|
|
|
|
), |
|
|
|
|
PlanExpression::In(e, l) => { |
|
|
|
|
let needed = self.eval_expression(e, tuple)?; |
|
|
|
|
let needed = self.eval_expression(e, tuple, options)?; |
|
|
|
|
let mut error = false; |
|
|
|
|
for possible in l { |
|
|
|
|
if let Some(possible) = self.eval_expression(possible, tuple) { |
|
|
|
|
if let Some(possible) = self.eval_expression(possible, tuple, options) { |
|
|
|
|
if Some(true) == self.equals(needed, possible) { |
|
|
|
|
return Some(true.into()); |
|
|
|
|
} |
|
|
|
@ -768,25 +787,25 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
Some(false.into()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
PlanExpression::Add(a, b) => Some(match self.parse_numeric_operands(a, b, tuple)? { |
|
|
|
|
PlanExpression::Add(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { |
|
|
|
|
NumericBinaryOperands::Float(v1, v2) => (v1 + v2).into(), |
|
|
|
|
NumericBinaryOperands::Double(v1, v2) => (v1 + v2).into(), |
|
|
|
|
NumericBinaryOperands::Integer(v1, v2) => v1.checked_add(v2)?.into(), |
|
|
|
|
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_add(v2)?.into(), |
|
|
|
|
}), |
|
|
|
|
PlanExpression::Sub(a, b) => Some(match self.parse_numeric_operands(a, b, tuple)? { |
|
|
|
|
PlanExpression::Sub(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { |
|
|
|
|
NumericBinaryOperands::Float(v1, v2) => (v1 - v2).into(), |
|
|
|
|
NumericBinaryOperands::Double(v1, v2) => (v1 - v2).into(), |
|
|
|
|
NumericBinaryOperands::Integer(v1, v2) => v1.checked_sub(v2)?.into(), |
|
|
|
|
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_sub(v2)?.into(), |
|
|
|
|
}), |
|
|
|
|
PlanExpression::Mul(a, b) => Some(match self.parse_numeric_operands(a, b, tuple)? { |
|
|
|
|
PlanExpression::Mul(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { |
|
|
|
|
NumericBinaryOperands::Float(v1, v2) => (v1 * v2).into(), |
|
|
|
|
NumericBinaryOperands::Double(v1, v2) => (v1 * v2).into(), |
|
|
|
|
NumericBinaryOperands::Integer(v1, v2) => v1.checked_mul(v2)?.into(), |
|
|
|
|
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_mul(v2)?.into(), |
|
|
|
|
}), |
|
|
|
|
PlanExpression::Div(a, b) => Some(match self.parse_numeric_operands(a, b, tuple)? { |
|
|
|
|
PlanExpression::Div(a, b) => Some(match self.parse_numeric_operands(a, b, tuple, options)? { |
|
|
|
|
NumericBinaryOperands::Float(v1, v2) => (v1 / v2).into(), |
|
|
|
|
NumericBinaryOperands::Double(v1, v2) => (v1 / v2).into(), |
|
|
|
|
NumericBinaryOperands::Integer(v1, v2) => Decimal::from_i128(v1)? |
|
|
|
@ -794,14 +813,14 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
.into(), |
|
|
|
|
NumericBinaryOperands::Decimal(v1, v2) => v1.checked_div(v2)?.into(), |
|
|
|
|
}), |
|
|
|
|
PlanExpression::UnaryPlus(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::UnaryPlus(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some((*value).into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some((*value).into()), |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some((value).into()), |
|
|
|
|
EncodedTerm::DecimalLiteral(value) => Some((value).into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::UnaryMinus(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::UnaryMinus(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some((-*value).into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some((-*value).into()), |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some((-value).into()), |
|
|
|
@ -809,12 +828,12 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::UnaryNot(e) => self |
|
|
|
|
.to_bool(self.eval_expression(e, tuple)?) |
|
|
|
|
.to_bool(self.eval_expression(e, tuple, options)?) |
|
|
|
|
.map(|v| (!v).into()), |
|
|
|
|
PlanExpression::Str(e) => Some(EncodedTerm::StringLiteral { |
|
|
|
|
value_id: self.to_string_id(self.eval_expression(e, tuple)?)?, |
|
|
|
|
value_id: self.to_string_id(self.eval_expression(e, tuple, options)?)?, |
|
|
|
|
}), |
|
|
|
|
PlanExpression::Lang(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Lang(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::LangStringLiteral { language_id, .. } => { |
|
|
|
|
Some(EncodedTerm::StringLiteral { |
|
|
|
|
value_id: language_id, |
|
|
|
@ -825,9 +844,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
}, |
|
|
|
|
PlanExpression::LangMatches(language_tag, language_range) => { |
|
|
|
|
let language_tag = |
|
|
|
|
self.to_simple_string(self.eval_expression(language_tag, tuple)?)?; |
|
|
|
|
self.to_simple_string(self.eval_expression(language_tag, tuple, options)?)?; |
|
|
|
|
let language_range = |
|
|
|
|
self.to_simple_string(self.eval_expression(language_range, tuple)?)?; |
|
|
|
|
self.to_simple_string(self.eval_expression(language_range, tuple, options)?)?; |
|
|
|
|
Some( |
|
|
|
|
if &*language_range == "*" { |
|
|
|
|
!language_tag.is_empty() |
|
|
|
@ -845,10 +864,10 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
.into(), |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
PlanExpression::Datatype(e) => self.eval_expression(e, tuple)?.datatype(), |
|
|
|
|
PlanExpression::Datatype(e) => self.eval_expression(e, tuple, options)?.datatype(), |
|
|
|
|
PlanExpression::Bound(v) => Some(has_tuple_value(*v, tuple).into()), |
|
|
|
|
PlanExpression::IRI(e) => { |
|
|
|
|
let iri_id = match self.eval_expression(e, tuple)? { |
|
|
|
|
let iri_id = match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::NamedNode { iri_id } => Some(iri_id), |
|
|
|
|
EncodedTerm::StringLiteral { value_id } => Some(value_id), |
|
|
|
|
_ => None, |
|
|
|
@ -864,7 +883,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
PlanExpression::BNode(id) => match id { |
|
|
|
|
Some(id) => { |
|
|
|
|
if let EncodedTerm::StringLiteral { value_id } = |
|
|
|
|
self.eval_expression(id, tuple)? |
|
|
|
|
self.eval_expression(id, tuple, options)? |
|
|
|
|
{ |
|
|
|
|
Some(EncodedTerm::BlankNode { |
|
|
|
|
id: *self |
|
|
|
@ -883,28 +902,28 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
}), |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Rand => Some(random::<f64>().into()), |
|
|
|
|
PlanExpression::Abs(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Abs(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some(value.checked_abs()?.into()), |
|
|
|
|
EncodedTerm::DecimalLiteral(value) => Some(value.abs().into()), |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some(value.abs().into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some(value.abs().into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Ceil(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Ceil(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::DecimalLiteral(value) => Some(value.ceil().into()), |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some(value.ceil().into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some(value.ceil().into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Floor(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Floor(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::DecimalLiteral(value) => Some(value.floor().into()), |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some(value.floor().into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some(value.floor().into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Round(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Round(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::DecimalLiteral(value) => Some( |
|
|
|
|
value |
|
|
|
@ -920,7 +939,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
let mut language = None; |
|
|
|
|
for e in l { |
|
|
|
|
let (value, e_language) = |
|
|
|
|
self.to_string_and_language(self.eval_expression(e, tuple)?)?; |
|
|
|
|
self.to_string_and_language(self.eval_expression(e, tuple, options)?)?; |
|
|
|
|
if let Some(lang) = language { |
|
|
|
|
if lang != e_language { |
|
|
|
|
language = Some(None) |
|
|
|
@ -934,17 +953,17 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
PlanExpression::SubStr(source, starting_loc, length) => { |
|
|
|
|
let (source, language) = |
|
|
|
|
self.to_string_and_language(self.eval_expression(source, tuple)?)?; |
|
|
|
|
self.to_string_and_language(self.eval_expression(source, tuple, options)?)?; |
|
|
|
|
|
|
|
|
|
let starting_location: usize = if let EncodedTerm::IntegerLiteral(v) = |
|
|
|
|
self.eval_expression(starting_loc, tuple)? |
|
|
|
|
self.eval_expression(starting_loc, tuple, options)? |
|
|
|
|
{ |
|
|
|
|
v.try_into().ok()? |
|
|
|
|
} else { |
|
|
|
|
return None; |
|
|
|
|
}; |
|
|
|
|
let length: Option<usize> = if let Some(length) = length { |
|
|
|
|
if let EncodedTerm::IntegerLiteral(v) = self.eval_expression(length, tuple)? { |
|
|
|
|
if let EncodedTerm::IntegerLiteral(v) = self.eval_expression(length, tuple, options)? { |
|
|
|
|
Some(v.try_into().ok()?) |
|
|
|
|
} else { |
|
|
|
|
return None; |
|
|
|
@ -976,45 +995,45 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
PlanExpression::StrLen(arg) => Some( |
|
|
|
|
(self |
|
|
|
|
.to_string(self.eval_expression(arg, tuple)?)? |
|
|
|
|
.to_string(self.eval_expression(arg, tuple, options)?)? |
|
|
|
|
.chars() |
|
|
|
|
.count() as i128) |
|
|
|
|
.into(), |
|
|
|
|
), |
|
|
|
|
PlanExpression::Replace(arg, pattern, replacement, flags) => { |
|
|
|
|
let regex = self.compile_pattern( |
|
|
|
|
self.eval_expression(pattern, tuple)?, |
|
|
|
|
self.eval_expression(pattern, tuple, options)?, |
|
|
|
|
if let Some(flags) = flags { |
|
|
|
|
Some(self.eval_expression(flags, tuple)?) |
|
|
|
|
Some(self.eval_expression(flags, tuple, options)?) |
|
|
|
|
} else { |
|
|
|
|
None |
|
|
|
|
}, |
|
|
|
|
)?; |
|
|
|
|
let (text, language) = |
|
|
|
|
self.to_string_and_language(self.eval_expression(arg, tuple)?)?; |
|
|
|
|
self.to_string_and_language(self.eval_expression(arg, tuple, options)?)?; |
|
|
|
|
let replacement = |
|
|
|
|
self.to_simple_string(self.eval_expression(replacement, tuple)?)?; |
|
|
|
|
self.to_simple_string(self.eval_expression(replacement, tuple, options)?)?; |
|
|
|
|
self.build_plain_literal(®ex.replace_all(&text, &replacement as &str), language) |
|
|
|
|
} |
|
|
|
|
PlanExpression::UCase(e) => { |
|
|
|
|
let (value, language) = |
|
|
|
|
self.to_string_and_language(self.eval_expression(e, tuple)?)?; |
|
|
|
|
self.to_string_and_language(self.eval_expression(e, tuple, options)?)?; |
|
|
|
|
self.build_plain_literal(&value.to_uppercase(), language) |
|
|
|
|
} |
|
|
|
|
PlanExpression::LCase(e) => { |
|
|
|
|
let (value, language) = |
|
|
|
|
self.to_string_and_language(self.eval_expression(e, tuple)?)?; |
|
|
|
|
self.to_string_and_language(self.eval_expression(e, tuple, options)?)?; |
|
|
|
|
self.build_plain_literal(&value.to_lowercase(), language) |
|
|
|
|
} |
|
|
|
|
PlanExpression::StrStarts(arg1, arg2) => { |
|
|
|
|
let (arg1, arg2, _) = self.to_argument_compatible_strings( |
|
|
|
|
self.eval_expression(arg1, tuple)?, |
|
|
|
|
self.eval_expression(arg2, tuple)?, |
|
|
|
|
self.eval_expression(arg1, tuple, options)?, |
|
|
|
|
self.eval_expression(arg2, tuple, options)?, |
|
|
|
|
)?; |
|
|
|
|
Some((&arg1).starts_with(&arg2 as &str).into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::EncodeForURI(ltrl) => { |
|
|
|
|
let ltlr = self.to_string(self.eval_expression(ltrl, tuple)?)?; |
|
|
|
|
let ltlr = self.to_string(self.eval_expression(ltrl, tuple, options)?)?; |
|
|
|
|
let mut result = Vec::with_capacity(ltlr.len()); |
|
|
|
|
for c in ltlr.bytes() { |
|
|
|
|
match c { |
|
|
|
@ -1042,22 +1061,22 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
PlanExpression::StrEnds(arg1, arg2) => { |
|
|
|
|
let (arg1, arg2, _) = self.to_argument_compatible_strings( |
|
|
|
|
self.eval_expression(arg1, tuple)?, |
|
|
|
|
self.eval_expression(arg2, tuple)?, |
|
|
|
|
self.eval_expression(arg1, tuple, options)?, |
|
|
|
|
self.eval_expression(arg2, tuple, options)?, |
|
|
|
|
)?; |
|
|
|
|
Some((&arg1).ends_with(&arg2 as &str).into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::Contains(arg1, arg2) => { |
|
|
|
|
let (arg1, arg2, _) = self.to_argument_compatible_strings( |
|
|
|
|
self.eval_expression(arg1, tuple)?, |
|
|
|
|
self.eval_expression(arg2, tuple)?, |
|
|
|
|
self.eval_expression(arg1, tuple, options)?, |
|
|
|
|
self.eval_expression(arg2, tuple, options)?, |
|
|
|
|
)?; |
|
|
|
|
Some((&arg1).contains(&arg2 as &str).into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::StrBefore(arg1, arg2) => { |
|
|
|
|
let (arg1, arg2, language) = self.to_argument_compatible_strings( |
|
|
|
|
self.eval_expression(arg1, tuple)?, |
|
|
|
|
self.eval_expression(arg2, tuple)?, |
|
|
|
|
self.eval_expression(arg1, tuple, options)?, |
|
|
|
|
self.eval_expression(arg2, tuple, options)?, |
|
|
|
|
)?; |
|
|
|
|
if let Some(position) = (&arg1).find(&arg2 as &str) { |
|
|
|
|
self.build_plain_literal(&arg1[..position], language) |
|
|
|
@ -1067,8 +1086,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
PlanExpression::StrAfter(arg1, arg2) => { |
|
|
|
|
let (arg1, arg2, language) = self.to_argument_compatible_strings( |
|
|
|
|
self.eval_expression(arg1, tuple)?, |
|
|
|
|
self.eval_expression(arg2, tuple)?, |
|
|
|
|
self.eval_expression(arg1, tuple, options)?, |
|
|
|
|
self.eval_expression(arg2, tuple, options)?, |
|
|
|
|
)?; |
|
|
|
|
if let Some(position) = (&arg1).find(&arg2 as &str) { |
|
|
|
|
self.build_plain_literal(&arg1[position + arg2.len()..], language) |
|
|
|
@ -1076,40 +1095,40 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
Some(ENCODED_EMPTY_STRING_LITERAL) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
PlanExpression::Year(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Year(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::DateLiteral(date) => Some(date.year().into()), |
|
|
|
|
EncodedTerm::NaiveDateLiteral(date) => Some(date.year().into()), |
|
|
|
|
EncodedTerm::DateTimeLiteral(date_time) => Some(date_time.year().into()), |
|
|
|
|
EncodedTerm::NaiveDateTimeLiteral(date_time) => Some(date_time.year().into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Month(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Month(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::DateLiteral(date) => Some(date.year().into()), |
|
|
|
|
EncodedTerm::NaiveDateLiteral(date) => Some(date.month().into()), |
|
|
|
|
EncodedTerm::DateTimeLiteral(date_time) => Some(date_time.month().into()), |
|
|
|
|
EncodedTerm::NaiveDateTimeLiteral(date_time) => Some(date_time.month().into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Day(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Day(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::DateLiteral(date) => Some(date.year().into()), |
|
|
|
|
EncodedTerm::NaiveDateLiteral(date) => Some(date.day().into()), |
|
|
|
|
EncodedTerm::DateTimeLiteral(date_time) => Some(date_time.day().into()), |
|
|
|
|
EncodedTerm::NaiveDateTimeLiteral(date_time) => Some(date_time.day().into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Hours(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Hours(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::NaiveTimeLiteral(time) => Some(time.hour().into()), |
|
|
|
|
EncodedTerm::DateTimeLiteral(date_time) => Some(date_time.hour().into()), |
|
|
|
|
EncodedTerm::NaiveDateTimeLiteral(date_time) => Some(date_time.hour().into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Minutes(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Minutes(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::NaiveTimeLiteral(time) => Some(time.minute().into()), |
|
|
|
|
EncodedTerm::DateTimeLiteral(date_time) => Some(date_time.minute().into()), |
|
|
|
|
EncodedTerm::NaiveDateTimeLiteral(date_time) => Some(date_time.minute().into()), |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Seconds(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::Seconds(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::NaiveTimeLiteral(time) => Some( |
|
|
|
|
(Decimal::new(time.nanosecond().into(), 9) + Decimal::from(time.second())) |
|
|
|
|
.into(), |
|
|
|
@ -1127,7 +1146,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::Timezone(e) => { |
|
|
|
|
let timezone = match self.eval_expression(e, tuple)? { |
|
|
|
|
let timezone = match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::DateLiteral(date) => date.timezone(), |
|
|
|
|
EncodedTerm::DateTimeLiteral(date_time) => date_time.timezone(), |
|
|
|
|
_ => return None, |
|
|
|
@ -1161,7 +1180,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
PlanExpression::Tz(e) => { |
|
|
|
|
let timezone = match self.eval_expression(e, tuple)? { |
|
|
|
|
let timezone = match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::DateLiteral(date) => Some(date.timezone()), |
|
|
|
|
EncodedTerm::DateTimeLiteral(date_time) => Some(date_time.timezone()), |
|
|
|
|
EncodedTerm::NaiveDateLiteral(_) |
|
|
|
@ -1192,38 +1211,38 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
.to_hyphenated() |
|
|
|
|
.encode_lower(&mut Uuid::encode_buffer()), |
|
|
|
|
), |
|
|
|
|
PlanExpression::MD5(arg) => self.hash::<Md5>(arg, tuple), |
|
|
|
|
PlanExpression::SHA1(arg) => self.hash::<Sha1>(arg, tuple), |
|
|
|
|
PlanExpression::SHA256(arg) => self.hash::<Sha256>(arg, tuple), |
|
|
|
|
PlanExpression::SHA384(arg) => self.hash::<Sha384>(arg, tuple), |
|
|
|
|
PlanExpression::SHA512(arg) => self.hash::<Sha512>(arg, tuple), |
|
|
|
|
PlanExpression::MD5(arg) => self.hash::<Md5>(arg, tuple, options), |
|
|
|
|
PlanExpression::SHA1(arg) => self.hash::<Sha1>(arg, tuple, options), |
|
|
|
|
PlanExpression::SHA256(arg) => self.hash::<Sha256>(arg, tuple, options), |
|
|
|
|
PlanExpression::SHA384(arg) => self.hash::<Sha384>(arg, tuple, options), |
|
|
|
|
PlanExpression::SHA512(arg) => self.hash::<Sha512>(arg, tuple, options), |
|
|
|
|
PlanExpression::Coalesce(l) => { |
|
|
|
|
for e in l { |
|
|
|
|
if let Some(result) = self.eval_expression(e, tuple) { |
|
|
|
|
if let Some(result) = self.eval_expression(e, tuple, options) { |
|
|
|
|
return Some(result); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
None |
|
|
|
|
} |
|
|
|
|
PlanExpression::If(a, b, c) => { |
|
|
|
|
if self.to_bool(self.eval_expression(a, tuple)?)? { |
|
|
|
|
self.eval_expression(b, tuple) |
|
|
|
|
if self.to_bool(self.eval_expression(a, tuple, options)?)? { |
|
|
|
|
self.eval_expression(b, tuple, options) |
|
|
|
|
} else { |
|
|
|
|
self.eval_expression(c, tuple) |
|
|
|
|
self.eval_expression(c, tuple, options) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
PlanExpression::StrLang(lexical_form, lang_tag) => { |
|
|
|
|
Some(EncodedTerm::LangStringLiteral { |
|
|
|
|
value_id: self |
|
|
|
|
.to_simple_string_id(self.eval_expression(lexical_form, tuple)?)?, |
|
|
|
|
.to_simple_string_id(self.eval_expression(lexical_form, tuple, options)?)?, |
|
|
|
|
language_id: self |
|
|
|
|
.to_simple_string_id(self.eval_expression(lang_tag, tuple)?)?, |
|
|
|
|
.to_simple_string_id(self.eval_expression(lang_tag, tuple, options)?)?, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
PlanExpression::StrDT(lexical_form, datatype) => { |
|
|
|
|
let value = self.to_simple_string(self.eval_expression(lexical_form, tuple)?)?; |
|
|
|
|
let value = self.to_simple_string(self.eval_expression(lexical_form, tuple, options)?)?; |
|
|
|
|
let datatype = if let EncodedTerm::NamedNode { iri_id } = |
|
|
|
|
self.eval_expression(datatype, tuple)? |
|
|
|
|
self.eval_expression(datatype, tuple, options)? |
|
|
|
|
{ |
|
|
|
|
self.dataset.get_str(iri_id).ok()? |
|
|
|
|
} else { |
|
|
|
@ -1238,19 +1257,19 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
.ok() |
|
|
|
|
} |
|
|
|
|
PlanExpression::SameTerm(a, b) => { |
|
|
|
|
Some((self.eval_expression(a, tuple)? == self.eval_expression(b, tuple)?).into()) |
|
|
|
|
Some((self.eval_expression(a, tuple, options)? == self.eval_expression(b, tuple, options)?).into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::IsIRI(e) => { |
|
|
|
|
Some(self.eval_expression(e, tuple)?.is_named_node().into()) |
|
|
|
|
Some(self.eval_expression(e, tuple, options)?.is_named_node().into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::IsBlank(e) => { |
|
|
|
|
Some(self.eval_expression(e, tuple)?.is_blank_node().into()) |
|
|
|
|
Some(self.eval_expression(e, tuple, options)?.is_blank_node().into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::IsLiteral(e) => { |
|
|
|
|
Some(self.eval_expression(e, tuple)?.is_literal().into()) |
|
|
|
|
Some(self.eval_expression(e, tuple, options)?.is_literal().into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::IsNumeric(e) => Some( |
|
|
|
|
match self.eval_expression(e, tuple)? { |
|
|
|
|
match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::FloatLiteral(_) |
|
|
|
|
| EncodedTerm::DoubleLiteral(_) |
|
|
|
|
| EncodedTerm::IntegerLiteral(_) |
|
|
|
@ -1261,24 +1280,24 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
), |
|
|
|
|
PlanExpression::Regex(text, pattern, flags) => { |
|
|
|
|
let regex = self.compile_pattern( |
|
|
|
|
self.eval_expression(pattern, tuple)?, |
|
|
|
|
self.eval_expression(pattern, tuple, options)?, |
|
|
|
|
if let Some(flags) = flags { |
|
|
|
|
Some(self.eval_expression(flags, tuple)?) |
|
|
|
|
Some(self.eval_expression(flags, tuple, options)?) |
|
|
|
|
} else { |
|
|
|
|
None |
|
|
|
|
}, |
|
|
|
|
)?; |
|
|
|
|
let text = self.to_string(self.eval_expression(text, tuple)?)?; |
|
|
|
|
let text = self.to_string(self.eval_expression(text, tuple, options)?)?; |
|
|
|
|
Some(regex.is_match(&text).into()) |
|
|
|
|
} |
|
|
|
|
PlanExpression::BooleanCast(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::BooleanCast(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::BooleanLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::StringLiteral { value_id } => { |
|
|
|
|
parse_boolean_str(&*self.dataset.get_str(value_id).ok()??) |
|
|
|
|
} |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::DoubleCast(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::DoubleCast(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some(value.to_f64()?.into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some(value.to_f64()?.into()), |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some(value.to_f64()?.into()), |
|
|
|
@ -1291,7 +1310,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::FloatCast(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::FloatCast(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some(value.to_f32()?.into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some(value.to_f32()?.into()), |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some(value.to_f32()?.into()), |
|
|
|
@ -1304,7 +1323,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::IntegerCast(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::IntegerCast(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some(value.to_i128()?.into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some(value.to_i128()?.into()), |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some(value.to_i128()?.into()), |
|
|
|
@ -1315,7 +1334,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::DecimalCast(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::DecimalCast(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::FloatLiteral(value) => Some(Decimal::from_f32(*value)?.into()), |
|
|
|
|
EncodedTerm::DoubleLiteral(value) => Some(Decimal::from_f64(*value)?.into()), |
|
|
|
|
EncodedTerm::IntegerLiteral(value) => Some(Decimal::from_i128(value)?.into()), |
|
|
|
@ -1333,7 +1352,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::DateCast(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::DateCast(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::DateLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::NaiveDateLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::DateTimeLiteral(value) => Some(value.date().into()), |
|
|
|
@ -1343,7 +1362,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::TimeCast(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::TimeCast(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::NaiveTimeLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::DateTimeLiteral(value) => Some(value.time().into()), |
|
|
|
|
EncodedTerm::NaiveDateTimeLiteral(value) => Some(value.time().into()), |
|
|
|
@ -1352,7 +1371,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::DateTimeCast(e) => match self.eval_expression(e, tuple)? { |
|
|
|
|
PlanExpression::DateTimeCast(e) => match self.eval_expression(e, tuple, options)? { |
|
|
|
|
EncodedTerm::DateTimeLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::NaiveDateTimeLiteral(value) => Some(value.into()), |
|
|
|
|
EncodedTerm::StringLiteral { value_id } => { |
|
|
|
@ -1361,7 +1380,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
_ => None, |
|
|
|
|
}, |
|
|
|
|
PlanExpression::StringCast(e) => Some(EncodedTerm::StringLiteral { |
|
|
|
|
value_id: self.to_string_id(self.eval_expression(e, tuple)?)?, |
|
|
|
|
value_id: self.to_string_id(self.eval_expression(e, tuple, options)?)?, |
|
|
|
|
}), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1526,15 +1545,16 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
regex_builder.build().ok() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn parse_numeric_operands( |
|
|
|
|
&self, |
|
|
|
|
fn parse_numeric_operands<'b>( |
|
|
|
|
&'b self, |
|
|
|
|
e1: &PlanExpression, |
|
|
|
|
e2: &PlanExpression, |
|
|
|
|
tuple: &[Option<EncodedTerm>], |
|
|
|
|
options: &QueryOptions<'b> |
|
|
|
|
) -> Option<NumericBinaryOperands> { |
|
|
|
|
NumericBinaryOperands::new( |
|
|
|
|
self.eval_expression(&e1, tuple)?, |
|
|
|
|
self.eval_expression(&e2, tuple)?, |
|
|
|
|
self.eval_expression(&e1, tuple, options)?, |
|
|
|
|
self.eval_expression(&e2, tuple, options)?, |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1674,15 +1694,16 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn cmp_according_to_expression( |
|
|
|
|
&self, |
|
|
|
|
fn cmp_according_to_expression<'b>( |
|
|
|
|
&'b self, |
|
|
|
|
tuple_a: &[Option<EncodedTerm>], |
|
|
|
|
tuple_b: &[Option<EncodedTerm>], |
|
|
|
|
expression: &PlanExpression, |
|
|
|
|
options: &QueryOptions<'b> |
|
|
|
|
) -> Ordering { |
|
|
|
|
self.cmp_terms( |
|
|
|
|
self.eval_expression(expression, tuple_a), |
|
|
|
|
self.eval_expression(expression, tuple_b), |
|
|
|
|
self.eval_expression(expression, tuple_a, options), |
|
|
|
|
self.eval_expression(expression, tuple_b, options), |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1793,12 +1814,13 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> { |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn hash<H: Digest>( |
|
|
|
|
&self, |
|
|
|
|
fn hash<'b, H: Digest>( |
|
|
|
|
&'b self, |
|
|
|
|
arg: &PlanExpression, |
|
|
|
|
tuple: &[Option<EncodedTerm>], |
|
|
|
|
options: &QueryOptions<'b> |
|
|
|
|
) -> Option<EncodedTerm> { |
|
|
|
|
let input = self.to_simple_string(self.eval_expression(arg, tuple)?)?; |
|
|
|
|
let input = self.to_simple_string(self.eval_expression(arg, tuple, options)?)?; |
|
|
|
|
let hash = hex::encode(H::new().chain(&input as &str).result()); |
|
|
|
|
self.build_string_literal(&hash) |
|
|
|
|
} |
|
|
|
@ -2067,6 +2089,7 @@ struct LeftJoinIterator<'a, S: StoreConnection + 'a> { |
|
|
|
|
right_plan: &'a PlanNode, |
|
|
|
|
left_iter: EncodedTuplesIterator<'a>, |
|
|
|
|
current_right: EncodedTuplesIterator<'a>, |
|
|
|
|
options: &'a QueryOptions<'a>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'a, S: StoreConnection> Iterator for LeftJoinIterator<'a, S> { |
|
|
|
@ -2078,7 +2101,7 @@ impl<'a, S: StoreConnection> Iterator for LeftJoinIterator<'a, S> { |
|
|
|
|
} |
|
|
|
|
match self.left_iter.next()? { |
|
|
|
|
Ok(left_tuple) => { |
|
|
|
|
self.current_right = self.eval.eval_plan(self.right_plan, left_tuple.clone()); |
|
|
|
|
self.current_right = self.eval.eval_plan(self.right_plan, left_tuple.clone(), self.options); |
|
|
|
|
if let Some(right_tuple) = self.current_right.next() { |
|
|
|
|
Some(right_tuple) |
|
|
|
|
} else { |
|
|
|
@ -2132,6 +2155,7 @@ struct UnionIterator<'a, S: StoreConnection + 'a> { |
|
|
|
|
input: EncodedTuple, |
|
|
|
|
current_iterator: EncodedTuplesIterator<'a>, |
|
|
|
|
current_plan: usize, |
|
|
|
|
options: &'a QueryOptions<'a>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'a, S: StoreConnection> Iterator for UnionIterator<'a, S> { |
|
|
|
@ -2147,13 +2171,13 @@ impl<'a, S: StoreConnection> Iterator for UnionIterator<'a, S> { |
|
|
|
|
} |
|
|
|
|
self.current_iterator = self |
|
|
|
|
.eval |
|
|
|
|
.eval_plan(&self.plans[self.current_plan], self.input.clone()); |
|
|
|
|
.eval_plan(&self.plans[self.current_plan], self.input.clone(), self.options); |
|
|
|
|
self.current_plan += 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct ConstructIterator<'a, S: StoreConnection> { |
|
|
|
|
struct ConstructIterator<'a, S: StoreConnection + 'a> { |
|
|
|
|
eval: &'a SimpleEvaluator<S>, |
|
|
|
|
iter: EncodedTuplesIterator<'a>, |
|
|
|
|
template: &'a [TripleTemplate], |
|
|
|
@ -2161,7 +2185,7 @@ struct ConstructIterator<'a, S: StoreConnection> { |
|
|
|
|
bnodes: Vec<BlankNode>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'a, S: StoreConnection> Iterator for ConstructIterator<'a, S> { |
|
|
|
|
impl<'a, S: StoreConnection + 'a> Iterator for ConstructIterator<'a, S> { |
|
|
|
|
type Item = Result<Triple>; |
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Result<Triple>> { |
|
|
|
@ -2230,7 +2254,7 @@ struct DescribeIterator<'a, S: StoreConnection + 'a> { |
|
|
|
|
quads: Box<dyn Iterator<Item = Result<EncodedQuad>> + 'a>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'a, S: StoreConnection> Iterator for DescribeIterator<'a, S> { |
|
|
|
|
impl<'a, S: StoreConnection + 'a> Iterator for DescribeIterator<'a, S> { |
|
|
|
|
type Item = Result<Triple>; |
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Result<Triple>> { |
|
|
|
|