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 store::encoded::EncodedQuadsStore;
use store::numeric_encoder::*;
use uuid::Uuid;
use Result;
const REGEX_SIZE_LIMIT: usize = 1_000_000;
@ -351,12 +352,12 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
PlanExpression::Equal(a, b) => {
let a = self.eval_expression(a, 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) => {
let a = self.eval_expression(a, 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(
(self.partial_cmp_literals(
@ -390,6 +391,24 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
Ordering::Greater => false,
}.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)? {
NumericBinaryOperands::Float(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()),
},
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) => {
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> {
match term {
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(
&self,
tuple_a: &[Option<EncodedTerm>],

@ -168,8 +168,7 @@ pub enum PlanExpression {
GreaterOrEq(Box<PlanExpression>, Box<PlanExpression>),
Lower(Box<PlanExpression>, Box<PlanExpression>),
LowerOrEq(Box<PlanExpression>, Box<PlanExpression>),
//In(Box<PlanExpression>, Vec<PlanExpression>),
//NotIn(Box<PlanExpression>, Vec<PlanExpression>),
In(Box<PlanExpression>, Vec<PlanExpression>),
Add(Box<PlanExpression>, Box<PlanExpression>),
Sub(Box<PlanExpression>, Box<PlanExpression>),
Mul(Box<PlanExpression>, Box<PlanExpression>),
@ -213,18 +212,22 @@ pub enum PlanExpression {
Minutes(Box<PlanExpression>),
Seconds(Box<PlanExpression>),
Timezone(Box<PlanExpression>),
Now(),
Now(),*/
UUID(),
StrUUID(),
MD5(Box<PlanExpression>),
/*MD5(Box<PlanExpression>),
SHA1(Box<PlanExpression>),
SHA256(Box<PlanExpression>),
SHA384(Box<PlanExpression>),
SHA512(Box<PlanExpression>),
SHA512(Box<PlanExpression>),*/
Coalesce(Vec<PlanExpression>),
If(Box<PlanExpression>, Box<PlanExpression>, Box<PlanExpression>),
If(
Box<PlanExpression>,
Box<PlanExpression>,
Box<PlanExpression>,
),
StrLang(Box<PlanExpression>, Box<PlanExpression>),
StrDT(Box<PlanExpression>, Box<PlanExpression>),*/
//StrDT(Box<PlanExpression>, Box<PlanExpression>),
SameTerm(Box<PlanExpression>, Box<PlanExpression>),
IsIRI(Box<PlanExpression>),
IsBlank(Box<PlanExpression>),
@ -247,7 +250,10 @@ pub enum PlanExpression {
impl PlanExpression {
fn add_variables(&self, set: &mut BTreeSet<usize>) {
match self {
PlanExpression::Constant(_) | PlanExpression::BNode(None) => (),
PlanExpression::Constant(_)
| PlanExpression::BNode(None)
| PlanExpression::UUID()
| PlanExpression::StrUUID() => (),
PlanExpression::Variable(v) | PlanExpression::Bound(v) => {
set.insert(*v);
}
@ -265,6 +271,7 @@ impl PlanExpression {
| PlanExpression::Div(a, b)
| PlanExpression::SameTerm(a, b)
| PlanExpression::LangMatches(a, b)
| PlanExpression::StrLang(a, b)
| PlanExpression::Regex(a, b, None) => {
a.add_variables(set);
b.add_variables(set);
@ -290,11 +297,27 @@ impl PlanExpression {
| PlanExpression::StringCast(e) => {
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)) => {
a.add_variables(set);
b.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(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(
Box::new(self.build_for_expression(a, 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)?)),
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(
Box::new(self.build_for_expression(a, 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(
&self,
term_or_variable: &TermOrVariable,

Loading…
Cancel
Save