use crate::model::*;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
pub use crate::model::pattern::TriplePattern;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum PropertyPath {
Predicate(NamedNode),
Inverse(Box<PropertyPath>),
Sequence(Box<PropertyPath>, Box<PropertyPath>),
Alternative(Box<PropertyPath>, Box<PropertyPath>),
ZeroOrMore(Box<PropertyPath>),
OneOrMore(Box<PropertyPath>),
ZeroOrOne(Box<PropertyPath>),
NegatedPropertySet(Vec<NamedNode>),
}
impl fmt::Display for PropertyPath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PropertyPath::Predicate(p) => write!(f, "{p}"),
PropertyPath::Inverse(p) => write!(f, "^{p}"),
PropertyPath::Sequence(a, b) => write!(f, "({a} / {b})"),
PropertyPath::Alternative(a, b) => write!(f, "({a} | {b})"),
PropertyPath::ZeroOrMore(p) => write!(f, "({p})*"),
PropertyPath::OneOrMore(p) => write!(f, "({p})+"),
PropertyPath::ZeroOrOne(p) => write!(f, "({p})?"),
PropertyPath::NegatedPropertySet(ps) => {
write!(f, "!(")?;
for (i, p) in ps.iter().enumerate() {
if i > 0 {
write!(f, " | ")?;
}
write!(f, "{p}")?;
}
write!(f, ")")
}
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expression {
Term(Term),
Variable(Variable),
And(Box<Expression>, Box<Expression>),
Or(Box<Expression>, Box<Expression>),
Not(Box<Expression>),
Equal(Box<Expression>, Box<Expression>),
NotEqual(Box<Expression>, Box<Expression>),
Less(Box<Expression>, Box<Expression>),
LessOrEqual(Box<Expression>, Box<Expression>),
Greater(Box<Expression>, Box<Expression>),
GreaterOrEqual(Box<Expression>, Box<Expression>),
Add(Box<Expression>, Box<Expression>),
Subtract(Box<Expression>, Box<Expression>),
Multiply(Box<Expression>, Box<Expression>),
Divide(Box<Expression>, Box<Expression>),
UnaryPlus(Box<Expression>),
UnaryMinus(Box<Expression>),
In(Box<Expression>, Vec<Expression>),
NotIn(Box<Expression>, Vec<Expression>),
Exists(Box<GraphPattern>),
NotExists(Box<GraphPattern>),
FunctionCall(Function, Vec<Expression>),
Bound(Variable),
If(Box<Expression>, Box<Expression>, Box<Expression>),
Coalesce(Vec<Expression>),
Literal(crate::model::Literal),
IsIri(Box<Expression>),
IsBlank(Box<Expression>),
IsLiteral(Box<Expression>),
IsNumeric(Box<Expression>),
Str(Box<Expression>),
Regex(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Function {
Str,
Lang,
LangMatches,
Datatype,
Iri,
Bnode,
StrDt,
StrLang,
StrLen,
SubStr,
UCase,
LCase,
StrStarts,
StrEnds,
Contains,
StrBefore,
StrAfter,
Encode,
Concat,
Replace,
Regex,
Abs,
Round,
Ceil,
Floor,
Rand,
Now,
Year,
Month,
Day,
Hours,
Minutes,
Seconds,
Timezone,
Tz,
Md5,
Sha1,
Sha256,
Sha384,
Sha512,
IsIri,
IsBlank,
IsLiteral,
IsNumeric,
Custom(NamedNode),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct AlgebraTriplePattern {
pub subject: TermPattern,
pub predicate: TermPattern,
pub object: TermPattern,
}
impl AlgebraTriplePattern {
pub fn new(subject: TermPattern, predicate: TermPattern, object: TermPattern) -> Self {
Self {
subject,
predicate,
object,
}
}
pub fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
f.write_str("(triple ")?;
self.subject.fmt_sse(f)?;
f.write_str(" ")?;
self.predicate.fmt_sse(f)?;
f.write_str(" ")?;
self.object.fmt_sse(f)?;
f.write_str(")")
}
}
impl fmt::Display for AlgebraTriplePattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {} {}", self.subject, self.predicate, self.object)
}
}
impl From<crate::model::pattern::TriplePattern> for Option<AlgebraTriplePattern> {
fn from(pattern: crate::model::pattern::TriplePattern) -> Self {
use crate::model::pattern::{ObjectPattern, PredicatePattern, SubjectPattern};
let subject = match pattern.subject? {
SubjectPattern::NamedNode(n) => TermPattern::NamedNode(n),
SubjectPattern::BlankNode(b) => TermPattern::BlankNode(b),
SubjectPattern::Variable(v) => TermPattern::Variable(v),
};
let predicate = match pattern.predicate? {
PredicatePattern::NamedNode(n) => TermPattern::NamedNode(n),
PredicatePattern::Variable(v) => TermPattern::Variable(v),
};
let object = match pattern.object? {
ObjectPattern::NamedNode(n) => TermPattern::NamedNode(n),
ObjectPattern::BlankNode(b) => TermPattern::BlankNode(b),
ObjectPattern::Literal(l) => TermPattern::Literal(l),
ObjectPattern::Variable(v) => TermPattern::Variable(v),
};
Some(AlgebraTriplePattern::new(subject, predicate, object))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum TermPattern {
NamedNode(NamedNode),
BlankNode(BlankNode),
Literal(Literal),
Variable(Variable),
QuotedTriple(Box<AlgebraTriplePattern>),
}
impl From<Variable> for TermPattern {
fn from(v: Variable) -> Self {
TermPattern::Variable(v)
}
}
impl From<NamedNode> for TermPattern {
fn from(n: NamedNode) -> Self {
TermPattern::NamedNode(n)
}
}
impl From<BlankNode> for TermPattern {
fn from(b: BlankNode) -> Self {
TermPattern::BlankNode(b)
}
}
impl From<Literal> for TermPattern {
fn from(l: Literal) -> Self {
TermPattern::Literal(l)
}
}
impl TermPattern {
pub fn is_variable(&self) -> bool {
matches!(self, TermPattern::Variable(_))
}
pub fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
match self {
TermPattern::NamedNode(node) => write!(f, "{node}"),
TermPattern::BlankNode(node) => write!(f, "{node}"),
TermPattern::Literal(literal) => write!(f, "{literal}"),
TermPattern::Variable(var) => write!(f, "{var}"),
TermPattern::QuotedTriple(triple) => {
write!(f, "<<")?;
triple.subject.fmt_sse(f)?;
write!(f, " ")?;
triple.predicate.fmt_sse(f)?;
write!(f, " ")?;
triple.object.fmt_sse(f)?;
write!(f, ">>")
}
}
}
}
impl fmt::Display for TermPattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TermPattern::NamedNode(n) => write!(f, "{n}"),
TermPattern::BlankNode(b) => write!(f, "{b}"),
TermPattern::Literal(l) => write!(f, "{l}"),
TermPattern::Variable(v) => write!(f, "{v}"),
TermPattern::QuotedTriple(triple) => {
write!(
f,
"<<{} {} {}>>",
triple.subject, triple.predicate, triple.object
)
}
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum GraphPattern {
Bgp(Vec<AlgebraTriplePattern>),
Path {
subject: TermPattern,
path: PropertyPath,
object: TermPattern,
},
Join(Box<GraphPattern>, Box<GraphPattern>),
LeftJoin {
left: Box<GraphPattern>,
right: Box<GraphPattern>,
condition: Option<Expression>,
},
Filter {
expr: Expression,
inner: Box<GraphPattern>,
},
Union(Box<GraphPattern>, Box<GraphPattern>),
Graph {
graph_name: TermPattern,
inner: Box<GraphPattern>,
},
Service {
service: TermPattern,
inner: Box<GraphPattern>,
silent: bool,
},
Group {
inner: Box<GraphPattern>,
variables: Vec<Variable>,
aggregates: Vec<(Variable, AggregateExpression)>,
},
Extend {
inner: Box<GraphPattern>,
variable: Variable,
expression: Expression,
},
Minus(Box<GraphPattern>, Box<GraphPattern>),
Values {
variables: Vec<Variable>,
bindings: Vec<Vec<Option<Term>>>,
},
OrderBy {
inner: Box<GraphPattern>,
order_by: Vec<OrderExpression>,
},
Project {
inner: Box<GraphPattern>,
variables: Vec<Variable>,
},
Distinct(Box<GraphPattern>),
Reduced(Box<GraphPattern>),
Slice {
inner: Box<GraphPattern>,
offset: usize,
limit: Option<usize>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AggregateExpression {
Count {
expr: Option<Box<Expression>>,
distinct: bool,
},
Sum {
expr: Box<Expression>,
distinct: bool,
},
Avg {
expr: Box<Expression>,
distinct: bool,
},
Min {
expr: Box<Expression>,
distinct: bool,
},
Max {
expr: Box<Expression>,
distinct: bool,
},
GroupConcat {
expr: Box<Expression>,
distinct: bool,
separator: Option<String>,
},
Sample {
expr: Box<Expression>,
distinct: bool,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OrderExpression {
Asc(Expression),
Desc(Expression),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum QueryForm {
Select {
variables: SelectVariables,
where_clause: GraphPattern,
distinct: bool,
reduced: bool,
order_by: Vec<OrderExpression>,
offset: usize,
limit: Option<usize>,
},
Construct {
template: Vec<AlgebraTriplePattern>,
where_clause: GraphPattern,
order_by: Vec<OrderExpression>,
offset: usize,
limit: Option<usize>,
},
Describe {
resources: Vec<TermPattern>,
where_clause: Option<GraphPattern>,
order_by: Vec<OrderExpression>,
offset: usize,
limit: Option<usize>,
},
Ask {
where_clause: GraphPattern,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum SelectVariables {
All,
Specific(Vec<Variable>),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Query {
pub base: Option<NamedNode>,
pub prefixes: HashMap<String, NamedNode>,
pub form: QueryForm,
pub dataset: Dataset,
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct Dataset {
pub default: Vec<NamedNode>,
pub named: Vec<NamedNode>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum UpdateOperation {
InsertData { data: Vec<Quad> },
DeleteData { data: Vec<Quad> },
DeleteWhere { pattern: Vec<QuadPattern> },
Modify {
delete: Option<Vec<QuadPattern>>,
insert: Option<Vec<QuadPattern>>,
where_clause: Box<GraphPattern>,
using: Dataset,
},
Load {
source: NamedNode,
destination: Option<NamedNode>,
silent: bool,
},
Clear { graph: GraphTarget, silent: bool },
Create { graph: NamedNode, silent: bool },
Drop { graph: GraphTarget, silent: bool },
Copy {
source: GraphTarget,
destination: GraphTarget,
silent: bool,
},
Move {
source: GraphTarget,
destination: GraphTarget,
silent: bool,
},
Add {
source: GraphTarget,
destination: GraphTarget,
silent: bool,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum GraphTarget {
Default,
Named(NamedNode),
All,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct QuadPattern {
pub subject: TermPattern,
pub predicate: TermPattern,
pub object: TermPattern,
pub graph: Option<TermPattern>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Update {
pub base: Option<NamedNode>,
pub prefixes: HashMap<String, NamedNode>,
pub operations: Vec<UpdateOperation>,
}