use arbitrary::{Arbitrary, Result, Unstructured};
use std::fmt;
use std::iter::once;
use std::ops::ControlFlow;
pub const DATA_TRIG: &str = "
@prefix : .
:1 :2 :3 , :4 ;
:5 true , 1 , 1.0 , 1e0 .
:3 :2 :4 ;
:5 false , 0 , 0.0 , 0e0 .
";
const NUMBER_OF_NAMED_NODES: u8 = 5;
const NUMBER_OF_VARIABLES: u8 = 4;
const LITERALS: [&str; 11] = [
"\"foo\"",
"\"foo\"^^",
"\"foo\"@en",
"true",
"false",
"0",
"0.0",
"0e0",
"1",
"1.0",
"1e0",
];
pub struct Query {
inner: QueryContent,
}
#[derive(Arbitrary)]
struct QueryContent {
// [1] QueryUnit ::= Query
// [2] Query ::= Prologue ( SelectQuery | ConstructQuery | DescribeQuery | AskQuery ) ValuesClause
variant: QueryVariant,
values_clause: ValuesClause,
}
#[derive(Arbitrary)]
enum QueryVariant {
Select(SelectQuery),
//TODO: Other variants!
}
impl<'a> Arbitrary<'a> for Query {
fn arbitrary(u: &mut Unstructured<'a>) -> Result {
Ok(Self {
inner: QueryContent::arbitrary(u)?,
})
}
fn arbitrary_take_rest(u: Unstructured<'a>) -> Result {
Ok(Self {
inner: QueryContent::arbitrary_take_rest(u)?,
})
}
fn size_hint(_depth: usize) -> (usize, Option) {
(20, None)
}
}
impl fmt::Display for Query {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner.variant {
QueryVariant::Select(s) => write!(f, "{s}"),
}?;
write!(f, "{}", self.inner.values_clause)
}
}
impl fmt::Debug for Query {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
#[derive(Arbitrary)]
struct SelectQuery {
// [7] SelectQuery ::= SelectClause DatasetClause* WhereClause SolutionModifier
select_clause: SelectClause,
where_clause: WhereClause,
solution_modifier: SolutionModifier,
}
impl fmt::Display for SelectQuery {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}{}{}",
self.select_clause, self.where_clause, self.solution_modifier
)
}
}
#[derive(Arbitrary)]
struct SubSelect {
// [8] SubSelect ::= SelectClause WhereClause SolutionModifier ValuesClause
select_clause: SelectClause,
where_clause: WhereClause,
solution_modifier: SolutionModifier,
values_clause: ValuesClause,
}
impl fmt::Display for SubSelect {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}{}{}{}",
self.select_clause, self.where_clause, self.solution_modifier, self.values_clause
)
}
}
#[derive(Arbitrary)]
struct SelectClause {
// [9] SelectClause ::= 'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( ( Var | ( '(' Expression 'AS' Var ')' ) )+ | '*' )
option: Option,
values: SelectValues,
}
#[derive(Arbitrary)]
enum SelectOption {
Distinct,
Reduced,
}
#[derive(Arbitrary)]
enum SelectValues {
Star,
Projection {
start: SelectProjection,
others: Vec,
},
}
#[derive(Arbitrary)]
enum SelectProjection {
Variable(Var),
Projection(Expression, Var),
}
impl fmt::Display for SelectClause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SELECT")?;
if let Some(option) = &self.option {
match option {
SelectOption::Distinct => write!(f, " DISTINCT"),
SelectOption::Reduced => write!(f, " REDUCED"),
}?;
}
match &self.values {
SelectValues::Star => write!(f, " *"),
SelectValues::Projection { start, others } => {
for e in once(start).chain(others) {
match e {
SelectProjection::Variable(v) => write!(f, " {v}"),
SelectProjection::Projection(e, v) => write!(f, " ({e} AS {v})"),
}?;
}
Ok(())
}
}
}
}
#[derive(Arbitrary)]
struct WhereClause {
// [17] WhereClause ::= 'WHERE'? GroupGraphPattern
with_where: bool,
group_graph_pattern: GroupGraphPattern,
}
impl fmt::Display for WhereClause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.with_where {
write!(f, " WHERE ")?;
}
write!(f, "{}", self.group_graph_pattern)
}
}
#[derive(Arbitrary)]
struct SolutionModifier {
// [18] SolutionModifier ::= GroupClause? HavingClause? OrderClause? LimitOffsetClauses?
group: Option,
having: Option,
#[cfg(feature = "order")]
order: Option,
#[cfg(feature = "limit-offset")]
limit_offset: Option,
}
impl fmt::Display for SolutionModifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(group) = &self.group {
write!(f, " {group}")?;
}
if let Some(having) = &self.having {
write!(f, " {having}")?;
}
#[cfg(feature = "order")]
if let Some(order) = &self.order {
write!(f, " {order}")?;
}
#[cfg(feature = "limit-offset")]
if let Some(limit_offset) = &self.limit_offset {
write!(f, " {limit_offset}")?;
}
Ok(())
}
}
#[derive(Arbitrary)]
struct GroupClause {
// [19] GroupClause ::= 'GROUP' 'BY' GroupCondition+
start: GroupCondition,
others: Vec,
}
impl fmt::Display for GroupClause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "GROUP BY {}", self.start)?;
for o in &self.others {
write!(f, " {o}")?;
}
Ok(())
}
}
#[derive(Arbitrary)]
enum GroupCondition {
// [20] GroupCondition ::= BuiltInCall | FunctionCall | '(' Expression ( 'AS' Var )? ')' | Var
BuiltInCall(BuiltInCall),
// TODO FunctionCall(FunctionCall)
Projection(Expression, Option),
Var(Var),
}
impl fmt::Display for GroupCondition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::BuiltInCall(c) => write!(f, "{c}"),
//Self::FunctionCall(c) => write!(f, "{}", c),
Self::Projection(e, v) => {
if let Some(v) = v {
write!(f, "({e} AS {v})")
} else {
write!(f, "({e})")
}
}
Self::Var(v) => write!(f, "{v}"),
}
}
}
#[derive(Arbitrary)]
struct HavingClause {
// [21] HavingClause ::= 'HAVING' HavingCondition+
start: HavingCondition,
others: Vec,
}
impl fmt::Display for HavingClause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "HAVING {}", self.start)?;
for o in &self.others {
write!(f, " {o}")?;
}
Ok(())
}
}
// [22] HavingCondition ::= Constraint
type HavingCondition = Constraint;
#[cfg(feature = "order")]
#[derive(Arbitrary)]
struct OrderClause {
// [23] OrderClause ::= 'ORDER' 'BY' OrderCondition+
start: OrderCondition,
others: Vec,
}
#[cfg(feature = "order")]
impl fmt::Display for OrderClause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ORDER BY {}", self.start)?;
for other in &self.others {
write!(f, " {other}")?;
}
Ok(())
}
}
#[cfg(feature = "order")]
#[derive(Arbitrary)]
enum OrderCondition {
// [24] OrderCondition ::= ( ( 'ASC' | 'DESC' ) BrackettedExpression ) | ( Constraint | Var )
BrackettedExpression {
is_asc: bool,
inner: BrackettedExpression,
},
Constraint(Constraint),
Var(Var),
}
#[cfg(feature = "order")]
impl fmt::Display for OrderCondition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::BrackettedExpression { is_asc, inner } => {
if *is_asc {
write!(f, "ASC{inner}")
} else {
write!(f, "DESC{inner}")
}
}
Self::Constraint(c) => write!(f, "{c}"),
Self::Var(v) => write!(f, "{v}"),
}
}
}
#[cfg(feature = "limit-offset")]
#[derive(Arbitrary)]
enum LimitOffsetClauses {
// [25] LimitOffsetClauses ::= LimitClause OffsetClause? | OffsetClause LimitClause?
LimitOffset(LimitClause, Option),
OffsetLimit(OffsetClause, Option),
}
#[cfg(feature = "limit-offset")]
impl fmt::Display for LimitOffsetClauses {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::LimitOffset(l, Some(o)) => write!(f, "{l} {o}"),
Self::LimitOffset(l, None) => write!(f, "{l}"),
Self::OffsetLimit(o, Some(l)) => write!(f, "{o} {l}"),
Self::OffsetLimit(o, None) => write!(f, "{o}"),
}
}
}
#[cfg(feature = "limit-offset")]
#[derive(Arbitrary)]
struct LimitClause {
// [26] LimitClause ::= 'LIMIT' INTEGER
value: u8,
}
#[cfg(feature = "limit-offset")]
impl fmt::Display for LimitClause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "LIMIT {}", self.value)
}
}
#[cfg(feature = "limit-offset")]
#[derive(Arbitrary)]
struct OffsetClause {
// [27] OffsetClause ::= 'OFFSET' INTEGER
value: u8,
}
#[cfg(feature = "limit-offset")]
impl fmt::Display for OffsetClause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "OFFSET {}", self.value)
}
}
#[derive(Arbitrary)]
struct ValuesClause {
// [28] ValuesClause ::= ( 'VALUES' DataBlock )?
value: Option,
}
impl fmt::Display for ValuesClause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(value) = &self.value {
write!(f, " VALUES {value}")
} else {
Ok(())
}
}
}
#[derive(Arbitrary)]
enum GroupGraphPattern {
// [53] GroupGraphPattern ::= '{' ( SubSelect | GroupGraphPatternSub ) '}'
GroupGraphPatternSub(GroupGraphPatternSub),
SubSelect(Box),
}
impl fmt::Display for GroupGraphPattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, " {{ ")?;
match self {
Self::GroupGraphPatternSub(p) => write!(f, "{p}"),
Self::SubSelect(s) => write!(f, "{s}"),
}?;
write!(f, " }} ")
}
}
#[derive(Arbitrary)]
struct GroupGraphPatternSub {
// [54] GroupGraphPatternSub ::= TriplesBlock? ( GraphPatternNotTriples '.'? TriplesBlock? )*
start: Option,
others: Vec,
}
#[derive(Arbitrary)]
struct GroupGraphPatternSubOtherBlock {
start: GraphPatternNotTriples,
with_dot: bool,
end: Option,
}
impl fmt::Display for GroupGraphPatternSub {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(start) = &self.start {
write!(f, "{start}")?;
}
for other in &self.others {
write!(f, "{}", other.start)?;
if other.with_dot {
write!(f, " . ")?;
}
if let Some(end) = &other.end {
write!(f, "{end}")?;
}
}
Ok(())
}
}
#[derive(Arbitrary)]
struct TriplesBlock {
// [55] TriplesBlock ::= TriplesSameSubjectPath ( '.' TriplesBlock? )?
start: TriplesSameSubjectPath,
end: Option