diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 69dba29e..52be919a 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -44,7 +44,7 @@ pub use failure::Error; pub type Result = ::std::result::Result; pub use crate::repository::Repository; pub use crate::repository::RepositoryConnection; -pub use crate::store::MemoryRepository; +pub use crate::store::{MemoryRepository, MemoryRepositoryConnection}; #[cfg(feature = "rocksdb")] pub use crate::store::RocksDbRepository; pub use crate::syntax::DatasetSyntax; diff --git a/lib/src/sparql/eval.rs b/lib/src/sparql/eval.rs index bc2410bc..e37fbfc5 100644 --- a/lib/src/sparql/eval.rs +++ b/lib/src/sparql/eval.rs @@ -169,14 +169,18 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { )))) as EncodedTuplesIterator<'_>; }, Some(pattern_fn) => { - let bindings = pattern_fn(graph_pattern.clone()).unwrap(); - let encoded = self.encode_bindings(variables, bindings); - let collected = encoded.collect::>(); - Box::new(JoinIterator { - left: vec![from], - right_iter: Box::new(collected.into_iter()), - buffered_results: vec![], - }) + match pattern_fn(graph_pattern.clone()) { + Ok(bindings) => { + let encoded = self.encode_bindings(variables, bindings); + let collected = encoded.collect::>(); + Box::new(JoinIterator { + left: vec![from], + right_iter: Box::new(collected.into_iter()), + buffered_results: vec![], + }) + }, + Err(err) => return Box::new(once(Err(err))) as EncodedTuplesIterator<'_> + } }, } } @@ -1644,17 +1648,12 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator { { let mut encoder = self.dataset.encoder(); let (binding_variables, iter) = BindingsIterator::destruct(iter); - let mut combined_variables = variables.clone().to_vec(); + let mut combined_variables = variables.to_vec(); for v in binding_variables.clone() { if !combined_variables.contains(&v) { combined_variables.resize(combined_variables.len() + 1, v); } } - - println!("binding_variables: {:?}", binding_variables.clone()); - println!("variables: {:?}", variables.clone()); - println!("combined_variables: {:?}", combined_variables.clone()); - println!("\n\n"); Box::new(iter.map(move |terms| { let mut encoded_terms = vec![None; combined_variables.len()]; for (i, term_option) in terms?.into_iter().enumerate() { diff --git a/lib/src/store/mod.rs b/lib/src/store/mod.rs index 03477db7..6a082621 100644 --- a/lib/src/store/mod.rs +++ b/lib/src/store/mod.rs @@ -6,7 +6,7 @@ pub(crate) mod numeric_encoder; mod rocksdb; pub use crate::sparql::GraphPattern; -pub use crate::store::memory::MemoryRepository; +pub use crate::store::memory::{MemoryRepository, MemoryRepositoryConnection}; #[cfg(feature = "rocksdb")] pub use crate::store::rocksdb::RocksDbRepository; diff --git a/lib/tests/service_test_cases.rs b/lib/tests/service_test_cases.rs index 342342f4..ada59976 100644 --- a/lib/tests/service_test_cases.rs +++ b/lib/tests/service_test_cases.rs @@ -2,87 +2,24 @@ use rudf::model::*; use rudf::{GraphSyntax, Repository, RepositoryConnection, MemoryRepository, Result}; use rudf::sparql::{BindingsIterator, GraphPattern, PreparedQuery, QueryOptions, QueryResult, ServiceHandler}; use failure::format_err; +use std::io::BufRead; -fn ex(id: String) -> Term { - Term::NamedNode(NamedNode::parse(format!("http://example.com/{}", &id)).unwrap()) -} - -fn foaf(id: String) -> Term { - Term::NamedNode(NamedNode::parse(format!("http://xmlns.com/foaf/0.1/{}", &id)).unwrap()) -} - -fn mailto(id: String) -> Term { - Term::NamedNode(NamedNode::parse(format!("mailto:{}", &id)).unwrap()) -} - -fn literal(str: String) -> Term { - Term::Literal(Literal::new_simple_literal(str)) -} - -/* -#[derive(Clone,Copy)] -struct SimpleServiceTest; -impl ServiceHandler for SimpleServiceTest { - fn handle<'a>(&'a self, named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)> { - Some(SimpleServiceTest::handle_service) - } -} -impl SimpleServiceTest { - fn handle_service<'a>(graph_pattern: GraphPattern) -> Result> { - let repository = MemoryRepository::default(); - let mut connection = repository.connection().unwrap(); - let file = b" ."; - connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap(); - let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, None).unwrap(); - let result = prepared_query.exec(&Some(SimpleServiceTest)).unwrap(); - match result { - QueryResult::Bindings(iterator) => { - let (variables, iter) = iterator.destruct(); - let cloned_iter = iter.collect::>().into_iter(); - let new_iter = BindingsIterator::new(variables, Box::new(cloned_iter)); - Ok(new_iter) - }, - _ => Err(format_err!("Excpected bindings but got another QueryResult")) - } - } -} -*/ #[test] fn simple_service_test() { struct TestServiceHandler; impl ServiceHandler for TestServiceHandler { - fn handle<'a>(&'a self, named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)> { + fn handle<'a>(&'a self, _named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)> { fn pattern_handler<'a>(graph_pattern: GraphPattern) -> Result> { - let repository = MemoryRepository::default(); - let mut connection = repository.connection().unwrap(); - let file = b" ."; - connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap(); - let query_options = QueryOptions::default(); - let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, &query_options).unwrap(); - let result = prepared_query.exec(&query_options).unwrap(); - match result { - QueryResult::Bindings(iterator) => { - let (variables, iter) = iterator.destruct(); - let cloned_iter = iter.collect::>().into_iter(); - let new_iter = BindingsIterator::new(variables, Box::new(cloned_iter)); - Ok(new_iter) - }, - _ => Err(format_err!("Excpected bindings but got another QueryResult")) - } + let triples = b" .".as_ref(); + do_pattern(triples, graph_pattern, QueryOptions::default()) }; Some(pattern_handler) } } - - - - let repository = MemoryRepository::default(); - let connection = repository.connection().unwrap(); - let query = r#" SELECT ?s ?p ?o WHERE @@ -91,26 +28,20 @@ fn simple_service_test() { { ?s ?p ?o } } - "#; + "#.to_string(); - let query_options = QueryOptions::default().with_service_handler(Box::new(TestServiceHandler)); - let prepared_query = connection.prepare_query(query, &query_options).unwrap(); - let results = prepared_query.exec(&query_options).unwrap(); - if let QueryResult::Bindings(results) = results { - let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::>(); - let solution = vec![ + let options = QueryOptions::default().with_service_handler(Box::new(TestServiceHandler)); + let results = do_query(b"".as_ref(), query, options).unwrap(); + let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::>(); + let solution = vec![ vec![ Some(ex(String::from("s"))), Some(ex(String::from("p"))), Some(ex(String::from("o"))) ], - ]; - assert_eq!(collected, solution); - } else { - assert_eq!(true, false); - } + ]; + assert_eq!(collected, solution); + } - - #[test] fn two_service_test() { @@ -118,12 +49,11 @@ fn two_service_test() { struct TwoServiceTest; impl ServiceHandler for TwoServiceTest { fn handle<'a>(&'a self, named_node: NamedNode) -> Option<(fn(GraphPattern) -> Result>)> { - println!("Handler called for {:?}", named_node); let service1 = NamedNode::parse("http://service1.org").unwrap(); let service2 = NamedNode::parse("http://service2.org").unwrap(); if named_node == service1 { Some(TwoServiceTest::handle_service1) } else if named_node == service2 { Some(TwoServiceTest::handle_service2) } - else { None} + else { None } } } @@ -131,57 +61,23 @@ fn two_service_test() { impl TwoServiceTest { fn handle_service1<'a>(graph_pattern: GraphPattern) -> Result> { - let repository = MemoryRepository::default(); - let mut connection = repository.connection().unwrap(); - let file = br#" + let triples = br#" "Bob" . "Alice" . - "#; - connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap(); - let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest)); - let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, &query_options).unwrap(); - let result = prepared_query.exec(&query_options).unwrap(); - match result { - QueryResult::Bindings(iterator) => { - let (variables, iter) = iterator.destruct(); - let cloned_iter = iter.collect::>().into_iter(); - let new_iter = BindingsIterator::new(variables, Box::new(cloned_iter)); - Ok(new_iter) - }, - _ => Err(format_err!("Excpected bindings but got another QueryResult")) - } + "#.as_ref(); + do_pattern(triples, graph_pattern, QueryOptions::default()) } - - - fn handle_service2<'a>(graph_pattern: GraphPattern) -> Result> { - let repository = MemoryRepository::default(); - let mut connection = repository.connection().unwrap(); - let file = br#" + let triples = br#" . . - "#; - connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None).unwrap(); - let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest)); - let prepared_query = connection.prepare_query_from_pattern(&graph_pattern, &query_options).unwrap(); - let result = prepared_query.exec(&query_options).unwrap(); - match result { - QueryResult::Bindings(iterator) => { - let (variables, iter) = iterator.destruct(); - let cloned_iter = iter.collect::>().into_iter(); - let new_iter = BindingsIterator::new(variables, Box::new(cloned_iter)); - Ok(new_iter) - }, - _ => Err(format_err!("Excpected bindings but got another QueryResult")) - } + "#.as_ref(); + do_pattern(triples, graph_pattern, QueryOptions::default()) } } - let repository = MemoryRepository::default(); - let connection = repository.connection().unwrap(); - let query = r#" PREFIX foaf: SELECT ?name ?mbox @@ -196,26 +92,74 @@ fn two_service_test() { } } ORDER BY ?name - "#; - - let query_options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest)); - let prepared_query = connection.prepare_query(query, &query_options).unwrap(); - let results = prepared_query.exec(&query_options).unwrap(); - if let QueryResult::Bindings(results) = results { - let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::>(); - for c in collected.clone() { - println!("{:?}", c); - } - println!("\n\n\n"); - let solution = vec![ + "#.to_string(); + + let options = QueryOptions::default().with_service_handler(Box::new(TwoServiceTest)); + let results = do_query(b"".as_ref(), query, options).unwrap(); + let collected = results.into_values_iter().map(move |b| b.unwrap()).collect::>(); + let solution = vec![ vec![ Some(literal("Alice".to_string())), Some(mailto("alice@example.com".to_string())) ], vec![ Some(literal("Bob".to_string())), Some(mailto("bob@example.com".to_string())) ], ]; - println!("Results: {:?}", collected); - assert_eq!(collected, solution); - } else { - assert_eq!(true, false); + assert_eq!(collected, solution); +} + +fn ex(id: String) -> Term { + Term::NamedNode(NamedNode::parse(format!("http://example.com/{}", &id)).unwrap()) +} + +fn mailto(id: String) -> Term { + Term::NamedNode(NamedNode::parse(format!("mailto:{}", &id)).unwrap()) +} + +fn literal(str: String) -> Term { + Term::Literal(Literal::new_simple_literal(str)) +} + +fn make_repository(reader: impl BufRead) -> Result { + let repository = MemoryRepository::default(); + let mut connection = repository.connection()?; + connection.load_graph(reader, GraphSyntax::NTriples, None, None).unwrap(); + Ok(repository) +} + +fn query_repository<'a>(repository: MemoryRepository, query: String, options: QueryOptions<'a>) -> Result> { + let connection = repository.connection()?; + let prepared_query = connection.prepare_query(&query, &options)?; + let result = prepared_query.exec(&options)?; + match result { + QueryResult::Bindings(iterator) => { + let (varaibles, iter) = iterator.destruct(); + let collected = iter.collect::>(); + Ok(BindingsIterator::new(varaibles, Box::new(collected.into_iter()))) + }, + _ => Err(format_err!("Excpected bindings but got another QueryResult")) + } +} + +//fn pattern_repository<'a>(repository: MemoryRepository, pattern: GraphPattern, options: QueryOptions<'a>) -> Result>>> { +fn pattern_repository<'a>(repository: MemoryRepository, pattern: GraphPattern, options: QueryOptions<'a>) -> Result> { + let connection = repository.connection()?; + let prepared_query = connection.prepare_query_from_pattern(&pattern, &options)?; + let result = prepared_query.exec(&options)?; + match result { + QueryResult::Bindings(iterator) => { + let (varaibles, iter) = iterator.destruct(); + let collected = iter.collect::>(); + Ok(BindingsIterator::new(varaibles, Box::new(collected.into_iter()))) + } + _ => Err(format_err!("Excpected bindings but got another QueryResult")) } } +//fn do_query<'a>(reader: impl BufRead, query: String, options: QueryOptions<'a>) -> Result>>> { +fn do_query<'a>(reader: impl BufRead, query: String, options: QueryOptions<'a>) -> Result> { + let repository = make_repository(reader)?; + query_repository(repository, query, options) +} +//fn do_pattern<'a>(reader: impl BufRead, pattern: GraphPattern, options: QueryOptions<'a>) -> Result>>> { +fn do_pattern<'a>(reader: impl BufRead, pattern: GraphPattern, options: QueryOptions<'a>) -> Result> { + let repository = make_repository(reader)?; + pattern_repository(repository, pattern, options) +}