Implements some SPARQL 1.1 functions

pull/10/head
Tpt 6 years ago
parent c3d11a7024
commit c7cd43217b
  1. 72
      lib/src/sparql/eval.rs
  2. 71
      lib/src/sparql/plan.rs

@ -22,6 +22,7 @@ use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use store::encoded::EncodedQuadsStore; use store::encoded::EncodedQuadsStore;
use store::numeric_encoder::*; use store::numeric_encoder::*;
use uuid::Uuid;
use Result; use Result;
const REGEX_SIZE_LIMIT: usize = 1_000_000; const REGEX_SIZE_LIMIT: usize = 1_000_000;
@ -351,12 +352,12 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
PlanExpression::Equal(a, b) => { PlanExpression::Equal(a, b) => {
let a = self.eval_expression(a, tuple)?; let a = self.eval_expression(a, tuple)?;
let b = self.eval_expression(b, tuple)?; let b = self.eval_expression(b, tuple)?;
Some((a == b || self.partial_cmp_literals(a, b) == Some(Ordering::Equal)).into()) Some(self.equals(a, b).into())
} }
PlanExpression::NotEqual(a, b) => { PlanExpression::NotEqual(a, b) => {
let a = self.eval_expression(a, tuple)?; let a = self.eval_expression(a, tuple)?;
let b = self.eval_expression(b, tuple)?; let b = self.eval_expression(b, tuple)?;
Some((a != b && self.partial_cmp_literals(a, b) != Some(Ordering::Equal)).into()) Some(self.not_equals(a, b).into())
} }
PlanExpression::Greater(a, b) => Some( PlanExpression::Greater(a, b) => Some(
(self.partial_cmp_literals( (self.partial_cmp_literals(
@ -390,6 +391,24 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
Ordering::Greater => false, Ordering::Greater => false,
}.into(), }.into(),
), ),
PlanExpression::In(e, l) => {
let needed = self.eval_expression(e, tuple)?;
let mut error = false;
for possible in l {
if let Some(possible) = self.eval_expression(possible, tuple) {
if self.equals(needed, possible) {
return Some(true.into());
}
} else {
error = true;
}
}
if error {
None
} else {
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)? {
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(),
@ -469,6 +488,39 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
}, },
None => Some(BlankNode::default().into()), None => Some(BlankNode::default().into()),
}, },
PlanExpression::UUID() => Some(EncodedTerm::NamedNode {
iri_id: self
.store
.insert_str(&Uuid::new_v4().to_urn().to_string())
.ok()?,
}),
PlanExpression::StrUUID() => Some(EncodedTerm::SimpleLiteral {
value_id: self
.store
.insert_str(&Uuid::new_v4().to_simple().to_string())
.ok()?,
}),
PlanExpression::Coalesce(l) => {
for e in l {
if let Some(result) = self.eval_expression(e, tuple) {
return Some(result);
}
}
None
}
PlanExpression::If(a, b, c) => if self.to_bool(self.eval_expression(a, tuple)?)? {
self.eval_expression(b, tuple)
} else {
self.eval_expression(c, tuple)
},
PlanExpression::StrLang(lexical_form, lang_tag) => {
Some(EncodedTerm::LangStringLiteral {
value_id: self
.to_simple_string_id(self.eval_expression(lexical_form, tuple)?)?,
language_id: self
.to_simple_string_id(self.eval_expression(lang_tag, tuple)?)?,
})
}
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)? == self.eval_expression(b, tuple)?).into())
} }
@ -669,6 +721,14 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
} }
} }
fn to_simple_string_id(&self, term: EncodedTerm) -> Option<u64> {
if let EncodedTerm::SimpleLiteral { value_id } = term {
Some(value_id)
} else {
None
}
}
fn to_string(&self, term: EncodedTerm) -> Option<String> { fn to_string(&self, term: EncodedTerm) -> Option<String> {
match term { match term {
EncodedTerm::SimpleLiteral { value_id } EncodedTerm::SimpleLiteral { value_id }
@ -762,6 +822,14 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
) )
} }
fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> bool {
(a == b || self.partial_cmp_literals(a, b) == Some(Ordering::Equal))
}
fn not_equals(&self, a: EncodedTerm, b: EncodedTerm) -> bool {
(a != b && self.partial_cmp_literals(a, b) != Some(Ordering::Equal))
}
fn cmp_according_to_expression( fn cmp_according_to_expression(
&self, &self,
tuple_a: &[Option<EncodedTerm>], tuple_a: &[Option<EncodedTerm>],

@ -168,8 +168,7 @@ pub enum PlanExpression {
GreaterOrEq(Box<PlanExpression>, Box<PlanExpression>), GreaterOrEq(Box<PlanExpression>, Box<PlanExpression>),
Lower(Box<PlanExpression>, Box<PlanExpression>), Lower(Box<PlanExpression>, Box<PlanExpression>),
LowerOrEq(Box<PlanExpression>, Box<PlanExpression>), LowerOrEq(Box<PlanExpression>, Box<PlanExpression>),
//In(Box<PlanExpression>, Vec<PlanExpression>), In(Box<PlanExpression>, Vec<PlanExpression>),
//NotIn(Box<PlanExpression>, Vec<PlanExpression>),
Add(Box<PlanExpression>, Box<PlanExpression>), Add(Box<PlanExpression>, Box<PlanExpression>),
Sub(Box<PlanExpression>, Box<PlanExpression>), Sub(Box<PlanExpression>, Box<PlanExpression>),
Mul(Box<PlanExpression>, Box<PlanExpression>), Mul(Box<PlanExpression>, Box<PlanExpression>),
@ -213,18 +212,22 @@ pub enum PlanExpression {
Minutes(Box<PlanExpression>), Minutes(Box<PlanExpression>),
Seconds(Box<PlanExpression>), Seconds(Box<PlanExpression>),
Timezone(Box<PlanExpression>), Timezone(Box<PlanExpression>),
Now(), Now(),*/
UUID(), UUID(),
StrUUID(), StrUUID(),
MD5(Box<PlanExpression>), /*MD5(Box<PlanExpression>),
SHA1(Box<PlanExpression>), SHA1(Box<PlanExpression>),
SHA256(Box<PlanExpression>), SHA256(Box<PlanExpression>),
SHA384(Box<PlanExpression>), SHA384(Box<PlanExpression>),
SHA512(Box<PlanExpression>), SHA512(Box<PlanExpression>),*/
Coalesce(Vec<PlanExpression>), Coalesce(Vec<PlanExpression>),
If(Box<PlanExpression>, Box<PlanExpression>, Box<PlanExpression>), If(
Box<PlanExpression>,
Box<PlanExpression>,
Box<PlanExpression>,
),
StrLang(Box<PlanExpression>, Box<PlanExpression>), StrLang(Box<PlanExpression>, Box<PlanExpression>),
StrDT(Box<PlanExpression>, Box<PlanExpression>),*/ //StrDT(Box<PlanExpression>, Box<PlanExpression>),
SameTerm(Box<PlanExpression>, Box<PlanExpression>), SameTerm(Box<PlanExpression>, Box<PlanExpression>),
IsIRI(Box<PlanExpression>), IsIRI(Box<PlanExpression>),
IsBlank(Box<PlanExpression>), IsBlank(Box<PlanExpression>),
@ -247,7 +250,10 @@ pub enum PlanExpression {
impl PlanExpression { impl PlanExpression {
fn add_variables(&self, set: &mut BTreeSet<usize>) { fn add_variables(&self, set: &mut BTreeSet<usize>) {
match self { match self {
PlanExpression::Constant(_) | PlanExpression::BNode(None) => (), PlanExpression::Constant(_)
| PlanExpression::BNode(None)
| PlanExpression::UUID()
| PlanExpression::StrUUID() => (),
PlanExpression::Variable(v) | PlanExpression::Bound(v) => { PlanExpression::Variable(v) | PlanExpression::Bound(v) => {
set.insert(*v); set.insert(*v);
} }
@ -265,6 +271,7 @@ impl PlanExpression {
| PlanExpression::Div(a, b) | PlanExpression::Div(a, b)
| PlanExpression::SameTerm(a, b) | PlanExpression::SameTerm(a, b)
| PlanExpression::LangMatches(a, b) | PlanExpression::LangMatches(a, b)
| PlanExpression::StrLang(a, b)
| PlanExpression::Regex(a, b, None) => { | PlanExpression::Regex(a, b, None) => {
a.add_variables(set); a.add_variables(set);
b.add_variables(set); b.add_variables(set);
@ -290,11 +297,27 @@ impl PlanExpression {
| PlanExpression::StringCast(e) => { | PlanExpression::StringCast(e) => {
e.add_variables(set); e.add_variables(set);
} }
PlanExpression::Coalesce(l) => {
for e in l {
e.add_variables(set);
}
}
PlanExpression::If(a, b, c) => {
a.add_variables(set);
b.add_variables(set);
c.add_variables(set);
}
PlanExpression::Regex(a, b, Some(c)) => { PlanExpression::Regex(a, b, Some(c)) => {
a.add_variables(set); a.add_variables(set);
b.add_variables(set); b.add_variables(set);
c.add_variables(set); c.add_variables(set);
} }
PlanExpression::In(e, l) => {
e.add_variables(set);
for e in l {
e.add_variables(set);
}
}
} }
} }
} }
@ -546,6 +569,14 @@ impl<'a, S: EncodedQuadsStore> PlanBuilder<'a, S> {
Box::new(self.build_for_expression(a, variables)?), Box::new(self.build_for_expression(a, variables)?),
Box::new(self.build_for_expression(b, variables)?), Box::new(self.build_for_expression(b, variables)?),
), ),
Expression::In(e, l) => PlanExpression::In(
Box::new(self.build_for_expression(e, variables)?),
self.expression_list(l, variables)?,
),
Expression::NotIn(e, l) => PlanExpression::UnaryNot(Box::new(PlanExpression::In(
Box::new(self.build_for_expression(e, variables)?),
self.expression_list(l, variables)?,
))),
Expression::Add(a, b) => PlanExpression::Add( Expression::Add(a, b) => PlanExpression::Add(
Box::new(self.build_for_expression(a, variables)?), Box::new(self.build_for_expression(a, variables)?),
Box::new(self.build_for_expression(b, variables)?), Box::new(self.build_for_expression(b, variables)?),
@ -592,6 +623,20 @@ impl<'a, S: EncodedQuadsStore> PlanBuilder<'a, S> {
Some(e) => Some(Box::new(self.build_for_expression(e, variables)?)), Some(e) => Some(Box::new(self.build_for_expression(e, variables)?)),
None => None, None => None,
}), }),
Expression::UUIDFunctionCall() => PlanExpression::UUID(),
Expression::StrUUIDFunctionCall() => PlanExpression::StrUUID(),
Expression::CoalesceFunctionCall(l) => {
PlanExpression::Coalesce(self.expression_list(l, variables)?)
}
Expression::IfFunctionCall(a, b, c) => PlanExpression::If(
Box::new(self.build_for_expression(a, variables)?),
Box::new(self.build_for_expression(b, variables)?),
Box::new(self.build_for_expression(c, variables)?),
),
Expression::StrLangFunctionCall(a, b) => PlanExpression::StrLang(
Box::new(self.build_for_expression(a, variables)?),
Box::new(self.build_for_expression(b, variables)?),
),
Expression::SameTermFunctionCall(a, b) => PlanExpression::SameTerm( Expression::SameTermFunctionCall(a, b) => PlanExpression::SameTerm(
Box::new(self.build_for_expression(a, variables)?), Box::new(self.build_for_expression(a, variables)?),
Box::new(self.build_for_expression(b, variables)?), Box::new(self.build_for_expression(b, variables)?),
@ -676,6 +721,16 @@ impl<'a, S: EncodedQuadsStore> PlanBuilder<'a, S> {
} }
} }
fn expression_list(
&self,
l: &[Expression],
variables: &mut Vec<Variable>,
) -> Result<Vec<PlanExpression>> {
l.iter()
.map(|e| self.build_for_expression(e, variables))
.collect()
}
fn pattern_value_from_term_or_variable( fn pattern_value_from_term_or_variable(
&self, &self,
term_or_variable: &TermOrVariable, term_or_variable: &TermOrVariable,

Loading…
Cancel
Save