setup ServiceHandler

pull/11/head
Dustin Whitney 5 years ago
parent e3fe4c5dc6
commit 40680956ba
  1. 312
      lib/src/sparql/eval.rs
  2. 20
      lib/src/sparql/mod.rs

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

@ -9,6 +9,7 @@ mod plan;
mod plan_builder; mod plan_builder;
mod xml_results; mod xml_results;
use crate::model::NamedNode;
use crate::sparql::algebra::QueryVariants; use crate::sparql::algebra::QueryVariants;
use crate::sparql::eval::SimpleEvaluator; use crate::sparql::eval::SimpleEvaluator;
use crate::sparql::parser::read_sparql_query; use crate::sparql::parser::read_sparql_query;
@ -19,6 +20,7 @@ use crate::store::StoreConnection;
use crate::Result; use crate::Result;
use std::fmt; use std::fmt;
pub use crate::sparql::algebra::GraphPattern;
pub use crate::sparql::model::BindingsIterator; pub use crate::sparql::model::BindingsIterator;
pub use crate::sparql::model::QueryResult; pub use crate::sparql::model::QueryResult;
pub use crate::sparql::model::QueryResultSyntax; pub use crate::sparql::model::QueryResultSyntax;
@ -27,7 +29,7 @@ pub use crate::sparql::model::Variable;
/// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/) /// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/)
pub trait PreparedQuery { pub trait PreparedQuery {
/// Evaluates the query and returns its results /// Evaluates the query and returns its results
fn exec(&self) -> Result<QueryResult>; fn exec<'a>(&'a self, options: &'a QueryOptions<'a>) -> Result<QueryResult<'a>>;
} }
/// An implementation of `PreparedQuery` for internal use /// An implementation of `PreparedQuery` for internal use
@ -115,32 +117,37 @@ impl<S: StoreConnection> SimplePreparedQuery<S> {
} }
impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> { impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> {
fn exec(&self) -> Result<QueryResult<'_>> { fn exec<'a>(&'a self, options: &'a QueryOptions<'a>) -> Result<QueryResult<'a>> {
match &self.0 { match &self.0 {
SimplePreparedQueryAction::Select { SimplePreparedQueryAction::Select {
plan, plan,
variables, variables,
evaluator, evaluator,
} => evaluator.evaluate_select_plan(&plan, &variables), } => evaluator.evaluate_select_plan(&plan, &variables, options),
SimplePreparedQueryAction::Ask { plan, evaluator } => { SimplePreparedQueryAction::Ask { plan, evaluator } => {
evaluator.evaluate_ask_plan(&plan) evaluator.evaluate_ask_plan(&plan, options)
} }
SimplePreparedQueryAction::Construct { SimplePreparedQueryAction::Construct {
plan, plan,
construct, construct,
evaluator, evaluator,
} => evaluator.evaluate_construct_plan(&plan, &construct), } => evaluator.evaluate_construct_plan(&plan, &construct, &options),
SimplePreparedQueryAction::Describe { plan, evaluator } => { SimplePreparedQueryAction::Describe { plan, evaluator } => {
evaluator.evaluate_describe_plan(&plan) evaluator.evaluate_describe_plan(&plan, &options)
} }
} }
} }
} }
pub trait ServiceHandler {
fn handle<'a>(&'a self, node: NamedNode) -> Option<(fn(GraphPattern) -> Result<BindingsIterator<'a>>)>;
}
/// Options for SPARQL query parsing and evaluation like the query base IRI /// Options for SPARQL query parsing and evaluation like the query base IRI
pub struct QueryOptions<'a> { pub struct QueryOptions<'a> {
pub(crate) base_iri: Option<&'a str>, pub(crate) base_iri: Option<&'a str>,
pub(crate) default_graph_as_union: bool, pub(crate) default_graph_as_union: bool,
pub(crate) service_handler: Option<Box<dyn ServiceHandler>>,
} }
impl<'a> Default for QueryOptions<'a> { impl<'a> Default for QueryOptions<'a> {
@ -148,6 +155,7 @@ impl<'a> Default for QueryOptions<'a> {
Self { Self {
base_iri: None, base_iri: None,
default_graph_as_union: false, default_graph_as_union: false,
service_handler: None as Option<Box<dyn ServiceHandler>>,
} }
} }
} }

Loading…
Cancel
Save