Skip to main content

oxirs_arq/
update_protocol_types.rs

1//! Domain types for the standalone SPARQL 1.1 Update protocol.
2//!
3//! This sibling module hosts the data structures used by the
4//! [`update_protocol`](crate::update_protocol) facade: concrete triples,
5//! pattern terms, triple patterns, the top-level [`SparqlUpdate`] enum,
6//! and the result / error types returned by the parser and executor.
7
8// ---------------------------------------------------------------------------
9// Domain types
10// ---------------------------------------------------------------------------
11
12/// A concrete RDF triple (no variables).
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct Triple {
15    pub s: String,
16    pub p: String,
17    pub o: String,
18}
19
20impl Triple {
21    /// Convenience constructor.
22    pub fn new(s: impl Into<String>, p: impl Into<String>, o: impl Into<String>) -> Self {
23        Self {
24            s: s.into(),
25            p: p.into(),
26            o: o.into(),
27        }
28    }
29}
30
31/// A position in a triple pattern – can be an IRI, a plain literal, a blank
32/// node, or a variable (placeholder for pattern matching).
33#[derive(Debug, Clone, PartialEq, Eq, Hash)]
34pub enum PatternTerm {
35    Iri(String),
36    Literal(String),
37    Variable(String),
38    BlankNode(String),
39}
40
41impl PatternTerm {
42    /// Returns `true` when this term is a variable (used during template instantiation).
43    pub fn is_variable(&self) -> bool {
44        matches!(self, PatternTerm::Variable(_))
45    }
46
47    /// Returns the variable name if this is a `Variable` variant.
48    pub fn variable_name(&self) -> Option<&str> {
49        if let PatternTerm::Variable(name) = self {
50            Some(name.as_str())
51        } else {
52            None
53        }
54    }
55}
56
57/// A triple pattern where any position may be a variable.
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct TriplePattern {
60    pub s: PatternTerm,
61    pub p: PatternTerm,
62    pub o: PatternTerm,
63}
64
65impl TriplePattern {
66    /// Construct a new triple pattern.
67    pub fn new(s: PatternTerm, p: PatternTerm, o: PatternTerm) -> Self {
68        Self { s, o, p }
69    }
70}
71
72// ---------------------------------------------------------------------------
73// DROP / CLEAR target type
74// ---------------------------------------------------------------------------
75
76/// Scope qualifier for `DROP` operations.
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub enum DropType {
79    /// A specific named graph identified by IRI.
80    Graph,
81    /// The default graph.
82    Default,
83    /// All named graphs.
84    Named,
85    /// Every graph in the dataset (default + all named).
86    All,
87}
88
89/// Scope qualifier for `CLEAR` operations.
90#[derive(Debug, Clone, PartialEq, Eq)]
91pub enum ClearType {
92    /// A specific named graph identified by IRI.
93    Graph,
94    /// The default graph.
95    Default,
96    /// All named graphs.
97    Named,
98    /// Every graph in the dataset.
99    All,
100}
101
102// ---------------------------------------------------------------------------
103// Top-level update enum
104// ---------------------------------------------------------------------------
105
106/// A single SPARQL 1.1 update operation.
107#[derive(Debug, Clone, PartialEq)]
108pub enum SparqlUpdate {
109    /// `INSERT DATA { … }` — adds concrete triples to the default graph.
110    InsertData(Vec<Triple>),
111
112    /// `DELETE DATA { … }` — removes concrete triples from the default graph.
113    DeleteData(Vec<Triple>),
114
115    /// `INSERT { template } WHERE { where_clause }` — pattern-based insert.
116    InsertWhere {
117        template: Vec<TriplePattern>,
118        where_clause: Vec<TriplePattern>,
119    },
120
121    /// `DELETE { template } WHERE { where_clause }` — pattern-based delete.
122    DeleteWhere {
123        template: Vec<TriplePattern>,
124        where_clause: Vec<TriplePattern>,
125    },
126
127    /// `DELETE { delete } INSERT { insert } WHERE { where_clause }` — combined modify.
128    Modify {
129        delete: Vec<TriplePattern>,
130        insert: Vec<TriplePattern>,
131        where_clause: Vec<TriplePattern>,
132    },
133
134    /// `CREATE [SILENT] GRAPH <iri>`.
135    CreateGraph { iri: String, silent: bool },
136
137    /// `DROP [SILENT] (GRAPH <iri> | DEFAULT | NAMED | ALL)`.
138    DropGraph {
139        iri: Option<String>,
140        silent: bool,
141        drop_type: DropType,
142    },
143
144    /// `CLEAR [SILENT] (GRAPH <iri> | DEFAULT | NAMED | ALL)`.
145    ClearGraph {
146        iri: Option<String>,
147        silent: bool,
148        clear_type: ClearType,
149    },
150
151    /// `COPY [SILENT] <source> TO <target>`.
152    CopyGraph {
153        source: String,
154        target: String,
155        silent: bool,
156    },
157
158    /// `MOVE [SILENT] <source> TO <target>`.
159    MoveGraph {
160        source: String,
161        target: String,
162        silent: bool,
163    },
164
165    /// `ADD [SILENT] <source> TO <target>`.
166    AddGraph {
167        source: String,
168        target: String,
169        silent: bool,
170    },
171
172    /// `LOAD [SILENT] <iri> [INTO GRAPH <into>]`.
173    Load {
174        iri: String,
175        into: Option<String>,
176        silent: bool,
177    },
178}
179
180// ---------------------------------------------------------------------------
181// Parse error
182// ---------------------------------------------------------------------------
183
184/// Error returned by `SparqlUpdateParser`.
185#[derive(Debug, Clone, PartialEq)]
186pub struct ParseError {
187    pub message: String,
188    /// Byte offset inside the input string where the error was detected.
189    pub position: usize,
190}
191
192impl ParseError {
193    /// Construct a `ParseError` at the given byte position.
194    pub(crate) fn at(position: usize, message: impl Into<String>) -> Self {
195        Self {
196            message: message.into(),
197            position,
198        }
199    }
200}
201
202impl std::fmt::Display for ParseError {
203    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
204        write!(
205            f,
206            "parse error at position {}: {}",
207            self.position, self.message
208        )
209    }
210}
211
212impl std::error::Error for ParseError {}
213
214// ---------------------------------------------------------------------------
215// UpdateResult
216// ---------------------------------------------------------------------------
217
218/// Summary of the changes made by a single `UpdateExecutor::execute` call.
219#[derive(Debug, Clone, Default, PartialEq, Eq)]
220pub struct UpdateResult {
221    /// Number of triples inserted into the default graph or named graphs.
222    pub triples_inserted: usize,
223    /// Number of triples deleted from the default graph or named graphs.
224    pub triples_deleted: usize,
225    /// Number of distinct graphs affected (created, cleared, populated, etc.).
226    pub graphs_affected: usize,
227}
228
229// ---------------------------------------------------------------------------
230// ArqError (thin wrapper)
231// ---------------------------------------------------------------------------
232
233/// Error type for the update executor.
234#[derive(Debug, Clone, PartialEq)]
235pub struct ArqError(pub String);
236
237impl std::fmt::Display for ArqError {
238    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
239        write!(f, "ARQ error: {}", self.0)
240    }
241}
242
243impl std::error::Error for ArqError {}