diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c4437b5..c6ec3db4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,13 @@ ## Master ### Added -- [SPARQL 1.1 Update](https://www.w3.org/TR/sparql11-update/) support for Rust, Python and JavaScript. +- [SPARQL 1.1 Update](https://www.w3.org/TR/sparql11-update/) support for Rust, Python and JavaScript. All store-like classes now provide an `update` method. - [SPARQL 1.1 Query Results CSV and TSV Formats](https://www.w3.org/TR/sparql11-results-csv-tsv/) serializers and TSV format parser. - The SPARQL Query and Update algebra is now public. - A simple built-in HTTP client. In the Rust library, is disabled by default behind the `http_client` feature. It powers SPARQL federation and SPARQL UPDATE `LOAD` operations. - `std::str::FromStr` implementations to `NamedNode`, `BlankNode`, `Literal`, `Term` and `Variable` allowing to easily parse Turtle/SPARQL serialization of these terms. - Optional Sled storage for `oxigraph_server`. +- `(Memory|RocksDB|Sled)Store::drop_graph`. ### Removed - The `default_graph_uris` and `named_graph_uris` parameters from `pyoxigraph` `query` methods. diff --git a/lib/src/store/memory.rs b/lib/src/store/memory.rs index c7283bbe..7eed33da 100644 --- a/lib/src/store/memory.rs +++ b/lib/src/store/memory.rs @@ -455,6 +455,35 @@ impl MemoryStore { dump_dataset(self.iter().map(Ok), writer, format) } + /// Removes a graph from this store. + /// + /// Usage example: + /// ``` + /// use oxigraph::MemoryStore; + /// use oxigraph::model::{NamedNode, Quad}; + /// + /// let ex = NamedNode::new("http://example.com")?; + /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), ex.clone()); + /// let store = MemoryStore::new(); + /// store.insert(quad.clone()); + /// assert_eq!(1, store.len()); + /// + /// store.drop_graph(&ex); + /// assert_eq!(0, store.len()); + /// # Result::<_,Box>::Ok(()) + /// ``` + pub fn drop_graph<'a>(&self, graph_name: impl Into>) { + if let Some(graph_name) = self + .get_encoded_graph_name(graph_name.into()) + .unwrap_infallible() + { + for quad in self.encoded_quads_for_pattern_inner(None, None, None, Some(graph_name)) { + let mut this = self; + this.remove_encoded(&quad).unwrap_infallible(); + } + } + } + #[allow(clippy::expect_used)] fn indexes(&self) -> RwLockReadGuard<'_, MemoryStoreIndexes> { self.indexes diff --git a/lib/src/store/rocksdb.rs b/lib/src/store/rocksdb.rs index ec4415bf..1beac4e7 100644 --- a/lib/src/store/rocksdb.rs +++ b/lib/src/store/rocksdb.rs @@ -352,6 +352,21 @@ impl RocksDbStore { dump_dataset(self.iter(), writer, syntax) } + /// Removes a graph from this store. + /// + /// See [`MemoryStore`](super::memory::MemoryStore::drop_graph()) for a usage example. + pub fn drop_graph<'a>(&self, graph_name: impl Into>) -> Result<(), io::Error> { + if let Some(graph_name) = self.get_encoded_graph_name(graph_name.into())? { + let mut transaction = self.auto_batch_writer(); + for quad in self.encoded_quads_for_pattern(None, None, None, Some(graph_name)) { + transaction.remove_encoded(&quad?)?; + } + transaction.apply() + } else { + Ok(()) + } + } + fn id2str_cf(&self) -> &ColumnFamily { get_cf(&self.db, ID2STR_CF) } diff --git a/lib/src/store/sled.rs b/lib/src/store/sled.rs index 772fa496..1f5670ed 100644 --- a/lib/src/store/sled.rs +++ b/lib/src/store/sled.rs @@ -385,6 +385,19 @@ impl SledStore { dump_dataset(self.iter(), writer, format) } + /// Removes a graph from this store. + /// + /// See [`MemoryStore`](super::memory::MemoryStore::drop_graph()) for a usage example. + pub fn drop_graph<'a>(&self, graph_name: impl Into>) -> Result<(), io::Error> { + if let Some(graph_name) = self.get_encoded_graph_name(graph_name.into())? { + for quad in self.encoded_quads_for_pattern(None, None, None, Some(graph_name)) { + let mut this = self; + this.remove_encoded(&quad?)?; + } + } + Ok(()) + } + fn contains_encoded(&self, quad: &EncodedQuad) -> Result { let mut buffer = Vec::with_capacity(4 * WRITTEN_TERM_MAX_SIZE); if quad.graph_name.is_default_graph() {