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 {}