Skip to content

Commit

Permalink
feat(base-iri): better support for base-iri especially in cursors
Browse files Browse the repository at this point in the history
  • Loading branch information
jgeluk committed Aug 31, 2022
1 parent 611c6c7 commit 3d637f3
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 22 deletions.
2 changes: 2 additions & 0 deletions src/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl Class {
.cursor(
tx.connection,
&Parameters::empty()?.fact_domain(FactDomain::ALL)?,
None,
)?
.count(tx);
#[allow(clippy::let_and_return)]
Expand Down Expand Up @@ -101,6 +102,7 @@ impl Class {
.cursor(
graph_connection.data_store_connection,
&Parameters::empty()?.fact_domain(FactDomain::ALL)?,
None,
)?
.count(tx);
#[allow(clippy::let_and_return)]
Expand Down
12 changes: 10 additions & 2 deletions src/cursor/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

use std::{ffi::CString, ptr, sync::Arc};

use iref::Iri;

use super::{CursorRow, OpenedCursor};
use crate::{
database_call,
error::Error,
namespace::DEFAULT_BASE_IRI,
root::{CCursor, CCursor_destroy, CDataStoreConnection_createCursor},
DataStoreConnection,
Parameters,
Expand Down Expand Up @@ -39,20 +42,25 @@ impl<'a> Cursor<'a> {
connection: &'a DataStoreConnection,
parameters: &Parameters,
statement: Statement<'a>,
base_iri: Option<Iri>,
) -> Result<Self, Error> {
assert!(!connection.inner.is_null());
assert!(!statement.prefixes.inner.is_null());
assert!(!statement.prefixes.inner.is_null());
let mut c_cursor: *mut CCursor = ptr::null_mut();
// let base_iri: *const std::os::raw::c_char = ptr::null();
let c_base_iri = if let Some(base_iri) = base_iri {
CString::new(base_iri.as_str()).unwrap()
} else {
CString::new(DEFAULT_BASE_IRI).unwrap()
};
let c_query = CString::new(statement.text.as_str()).unwrap();
let c_query_len: u64 = c_query.as_bytes().len() as u64;
log::trace!("Starting cursor for {:?}", c_query);
database_call!(
"creating a cursor",
CDataStoreConnection_createCursor(
connection.inner,
ptr::null(),
c_base_iri.as_ptr(),
statement.prefixes.inner,
c_query.as_ptr(),
c_query_len,
Expand Down
18 changes: 9 additions & 9 deletions src/data_store_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl<'a> DataStoreConnection<'a> {
);

let c_graph_name = graph.as_c_string()?;
let prefixes = Prefixes::default()?;
let prefixes = Prefixes::empty()?;
let file_name = CString::new(rdf_file).unwrap();
let format_name = CString::new(TEXT_TURTLE.as_ref()).unwrap();

Expand Down Expand Up @@ -281,7 +281,7 @@ impl<'a> DataStoreConnection<'a> {
) -> Result<u64, Error> {
let default_graph = DEFAULT_GRAPH.deref().as_display_iri();
Statement::new(
&Prefixes::default()?,
&Prefixes::empty()?,
formatdoc!(
r##"
SELECT ?graph ?s ?p ?o
Expand All @@ -297,7 +297,7 @@ impl<'a> DataStoreConnection<'a> {
)
.as_str(),
)?
.cursor(self, &Parameters::empty()?.fact_domain(fact_domain)?)?
.cursor(self, &Parameters::empty()?.fact_domain(fact_domain)?, None)?
.count(tx)
}

Expand All @@ -308,7 +308,7 @@ impl<'a> DataStoreConnection<'a> {
) -> Result<u64, Error> {
let default_graph = DEFAULT_GRAPH.deref().as_display_iri();
Statement::new(
&Prefixes::default()?,
&Prefixes::empty()?,
formatdoc!(
r##"
SELECT DISTINCT ?subject
Expand All @@ -326,7 +326,7 @@ impl<'a> DataStoreConnection<'a> {
)
.as_str(),
)?
.cursor(self, &Parameters::empty()?.fact_domain(fact_domain)?)?
.cursor(self, &Parameters::empty()?.fact_domain(fact_domain)?, None)?
.count(tx)
}

Expand All @@ -337,7 +337,7 @@ impl<'a> DataStoreConnection<'a> {
) -> Result<u64, Error> {
let default_graph = DEFAULT_GRAPH.deref().as_display_iri();
Statement::new(
&Prefixes::default()?,
&Prefixes::empty()?,
formatdoc!(
r##"
SELECT DISTINCT ?predicate
Expand All @@ -355,7 +355,7 @@ impl<'a> DataStoreConnection<'a> {
)
.as_str(),
)?
.cursor(self, &Parameters::empty()?.fact_domain(fact_domain)?)?
.cursor(self, &Parameters::empty()?.fact_domain(fact_domain)?, None)?
.count(tx)
}

Expand All @@ -366,7 +366,7 @@ impl<'a> DataStoreConnection<'a> {
) -> Result<u64, Error> {
let default_graph = DEFAULT_GRAPH.deref().as_display_iri();
Statement::new(
&Prefixes::default()?,
&Prefixes::empty()?,
formatdoc!(
r##"
SELECT DISTINCT ?ontology
Expand All @@ -384,7 +384,7 @@ impl<'a> DataStoreConnection<'a> {
)
.as_str(),
)?
.cursor(self, &Parameters::empty()?.fact_domain(fact_domain)?)?
.cursor(self, &Parameters::empty()?.fact_domain(fact_domain)?, None)?
.count(tx)
}

Expand Down
6 changes: 5 additions & 1 deletion src/graph_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,16 @@ impl<'a> GraphConnection<'a> {
.import_rdf_from_directory(root, &self.graph)
}

/// Get the number of triples using the given transaction.
///
/// TODO: Implement this with SPARQL COUNT (and compare performance)
pub fn get_triples_count(
&self,
tx: Arc<Transaction>,
fact_domain: FactDomain,
) -> Result<u64, Error> {
Statement::new(
&Prefixes::default()?,
&Prefixes::empty()?,
formatdoc!(
r##"
SELECT ?s ?p ?o
Expand All @@ -105,6 +108,7 @@ impl<'a> GraphConnection<'a> {
.cursor(
self.data_store_connection,
&Parameters::empty()?.fact_domain(fact_domain)?,
None,
)?
.count(tx)
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use lazy_static::lazy_static;
pub use lexical_value::LexicalValue;
pub use license::{find_license, RDFOX_DEFAULT_LICENSE_FILE_NAME, RDFOX_HOME};
pub use mime::Mime;
pub use namespace::*;
pub use parameters::{FactDomain, Parameters, PersistenceMode};
pub use predicate::Predicate;
pub use prefixes::{Prefix, Prefixes, PrefixesBuilder};
Expand All @@ -31,6 +32,7 @@ pub use statement::Statement;
pub use streamer::Streamer;
pub use transaction::Transaction;

// All supported MIME types
lazy_static! {
// As documented here: https://docs.oxfordsemantic.tech/5.6/programmatic-access-APIs.html#formats-encoding-sparql-query-results
pub static ref TEXT_TSV: Mime = Mime::from_str("text/tab-separated-values").unwrap();
Expand Down Expand Up @@ -73,6 +75,7 @@ mod graph;
mod graph_connection;
mod lexical_value;
mod license;
mod namespace;
mod parameters;
mod predicate;
mod prefixes;
Expand Down
43 changes: 43 additions & 0 deletions src/namespace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) 2018-2022, agnos.ai UK Ltd, all rights reserved.
//---------------------------------------------------------------

use iref::Iri;
use lazy_static::lazy_static;

use crate::Prefix;

type PrefixName<'a> = &'a str;

pub const DEFAULT_BASE_IRI: &str = "https://placeholder.kg";

const PREFIX_NAME_DCAT: PrefixName<'static> = "dcat:";
const PREFIX_NAME_OWL: PrefixName<'static> = "owl:";
const PREFIX_NAME_RDF: PrefixName<'static> = "rdf:";
const PREFIX_NAME_RDFS: PrefixName<'static> = "rdfs:";
const PREFIX_NAME_SKOS: PrefixName<'static> = "skos:";
const PREFIX_NAME_XSD: PrefixName<'static> = "xsd:";

const NS_IRI_DCAT: &str = "http://www.w3.org/ns/dcat#";
const NS_IRI_OWL: &str = "http://www.w3.org/2002/07/owl#";
const NS_IRI_RDF: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
const NS_IRI_RDFS: &str = "http://www.w3.org/2000/01/rdf-schema#";
const NS_IRI_SKOS: &str = "http://www.w3.org/2004/02/skos/core#";
const NS_IRI_XSD: &str = "http://www.w3.org/2001/XMLSchema#";

lazy_static! {
pub static ref NS_DCAT: Iri<'static> = Iri::new(NS_IRI_DCAT).unwrap();
pub static ref NS_OWL: Iri<'static> = Iri::new(NS_IRI_OWL).unwrap();
pub static ref NS_RDF: Iri<'static> = Iri::new(NS_IRI_RDF).unwrap();
pub static ref NS_RDFS: Iri<'static> = Iri::new(NS_IRI_RDFS).unwrap();
pub static ref NS_SKOS: Iri<'static> = Iri::new(NS_IRI_SKOS).unwrap();
pub static ref NS_XSD: Iri<'static> = Iri::new(NS_IRI_XSD).unwrap();
}

lazy_static! {
pub static ref PREFIX_DCAT: Prefix = Prefix::declare(PREFIX_NAME_DCAT, *NS_DCAT.deref());
pub static ref PREFIX_OWL: Prefix = Prefix::declare(PREFIX_NAME_OWL, *NS_OWL.deref());
pub static ref PREFIX_RDF: Prefix = Prefix::declare(PREFIX_NAME_RDF, *NS_RDF.deref());
pub static ref PREFIX_RDFS: Prefix = Prefix::declare(PREFIX_NAME_RDFS, *NS_RDFS.deref());
pub static ref PREFIX_SKOS: Prefix = Prefix::declare(PREFIX_NAME_SKOS, *NS_SKOS.deref());
pub static ref PREFIX_XSD: Prefix = Prefix::declare(PREFIX_NAME_XSD, *NS_XSD.deref());
}
20 changes: 14 additions & 6 deletions src/prefixes.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Copyright (c) 2018-2022, agnos.ai UK Ltd, all rights reserved.
//---------------------------------------------------------------

use std::{collections::HashMap, ffi::CString, fmt::Display, ptr};
use std::{collections::HashMap, ffi::CString, ops::Deref, ptr};

use iref::{Iri, IriBuf};

use crate::{
database_call,
error::Error,
namespace::{PREFIX_RDF, PREFIX_RDFS},
root::{
CPrefixes,
CPrefixes_DeclareResult as PrefixDeclareResult,
Expand All @@ -22,10 +23,10 @@ pub struct Prefixes {
map: HashMap<String, Prefix>,
}

impl Display for Prefixes {
impl std::fmt::Display for Prefixes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for prefix in self.map.values() {
writeln!(f, "PREFIX {prefix}")?
for _prefix in self.map.values() {
writeln!(f, "PREFIX {_prefix}")?
}
Ok(())
}
Expand All @@ -34,7 +35,7 @@ impl Display for Prefixes {
impl Prefixes {
pub fn builder() -> PrefixesBuilder { PrefixesBuilder::default() }

pub fn default() -> Result<Self, Error> {
pub fn empty() -> Result<Self, Error> {
let mut prefixes = Self {
inner: ptr::null_mut(),
map: HashMap::new(),
Expand All @@ -46,6 +47,13 @@ impl Prefixes {
Ok(prefixes)
}

/// Return the RDF and RDFS prefixes
pub fn default() -> Result<Self, Error> {
Self::empty()?
.add_prefix(PREFIX_RDF.deref())?
.add_prefix(PREFIX_RDFS.deref())
}

pub fn declare_prefix<'a>(&mut self, prefix: &Prefix) -> Result<PrefixDeclareResult, Error> {
log::trace!("Register prefix {prefix}");
if let Some(_already_registered) = self.map.insert(prefix.name.clone(), prefix.clone()) {
Expand Down Expand Up @@ -157,7 +165,7 @@ impl<'a> PrefixesBuilder {
}

pub fn build(self) -> Result<Prefixes, Error> {
let mut to_build = Prefixes::default()?;
let mut to_build = Prefixes::empty()?;
for prefix in self.prefixes {
to_build.declare_prefix(&prefix)?;
}
Expand Down
4 changes: 3 additions & 1 deletion src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use core::fmt::{Display, Formatter};
use std::{ffi::CString, ops::Deref};

use indoc::formatdoc;
use iref::Iri;

use crate::{error::Error, Cursor, DataStoreConnection, Parameters, Prefixes, DEFAULT_GRAPH};

Expand Down Expand Up @@ -35,8 +36,9 @@ impl<'a> Statement<'a> {
self,
connection: &'a DataStoreConnection,
parameters: &Parameters,
base_iri: Option<Iri>,
) -> Result<Cursor<'a>, Error> {
Cursor::create(connection, parameters, self)
Cursor::create(connection, parameters, self, base_iri)
}

pub(crate) fn as_c_string(&self) -> Result<CString, Error> {
Expand Down
8 changes: 5 additions & 3 deletions tests/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fn test_cursor_with_lexical_value(
) -> Result<(), Error> {
log::info!("test_cursor_with_lexical_value");
let graph = graph_connection.graph.as_display_iri();
let prefixes = Prefixes::default()?;
let prefixes = Prefixes::empty()?;
let query = Statement::new(
&prefixes,
formatdoc!(
Expand All @@ -136,6 +136,7 @@ fn test_cursor_with_lexical_value(
let mut cursor = query.clone().cursor(
graph_connection.data_store_connection,
&Parameters::empty()?.fact_domain(FactDomain::ASSERTED)?,
None,
)?;

let count = cursor.consume(tx, 10000, |row| {
Expand All @@ -157,7 +158,7 @@ fn test_cursor_with_resource_value(
) -> Result<(), Error> {
log::info!("test_cursor_with_resource_value");
let graph = graph_connection.graph.as_display_iri();
let prefixes = Prefixes::default()?;
let prefixes = Prefixes::empty()?;
let query = Statement::new(
&prefixes,
formatdoc!(
Expand All @@ -175,6 +176,7 @@ fn test_cursor_with_resource_value(
let mut cursor = query.clone().cursor(
graph_connection.data_store_connection,
&Parameters::empty()?.fact_domain(FactDomain::ASSERTED)?,
None,
)?;

let count = cursor.consume(tx, 10000, |row| {
Expand All @@ -195,7 +197,7 @@ fn test_run_query_to_nquads_buffer(
ds_connection: &DataStoreConnection,
) -> Result<(), Error> {
log::info!("test_run_query_to_nquads_buffer");
let prefixes = Prefixes::default()?;
let prefixes = Prefixes::empty()?;
let nquads_query = Statement::nquads_query(&prefixes)?;
let writer = std::io::stdout();
ds_connection.evaluate_to_stream(writer, &nquads_query, APPLICATION_N_QUADS.deref())?;
Expand Down

0 comments on commit 3d637f3

Please sign in to comment.