use std::time::Duration;
use crate::{connection, prelude::*};
#[derive(Clone)]
pub struct Connection
{
url: String,
}
impl Connection
{
pub fn new(url: impl Into<String>) -> Connection
{
Connection { url: url.into() }
}
}
impl connection::ConnectionPrivate for Connection {}
impl connection::Connection for Connection
{
async fn is_connected(&self) -> bool
{
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(5))
.build()
.unwrap();
client.get(&self.url).send().await.is_ok()
}
fn execute_query<TQuery>(
&self,
query: TQuery,
) -> Result<impl std::future::Future<Output = Result<dbc::Result>>>
where
TQuery: TryInto<dbc::Query>,
crate::Error: From<<TQuery as TryInto<dbc::Query>>::Error>,
{
let query = query.try_into()?;
Ok(async move {
let params = [
("query", query.query),
("Accept", "application/sparql-results+json".to_string()),
];
let client = reqwest::Client::new();
let uri_type = match query.query_type
{
dbc::QueryType::KDQL => "kdql",
dbc::QueryType::KRQL => "krql",
dbc::QueryType::SPARQL => "sparql",
dbc::QueryType::SQL => "sql",
};
let res = client
.post(format!("{}/{}.html", self.url, uri_type))
.form(¶ms)
.send()
.await?;
Ok(res.json::<crate::dbc::Result>().await?)
})
}
}
#[cfg(test)]
mod tests
{
use crate::prelude::*;
use queries::{kdql, krql};
#[tokio::test(flavor = "current_thread")]
async fn it_can_run_kr_query()
{
let mut store =
crate::test::create_store(crate::test::create_store_configuration().set_web_port(8888));
store.start().unwrap();
let q = krql::Test {
return_value: Some(12.into()),
..Default::default()
};
let c = crate::http::Connection::new("http://localhost:8888");
crate::test::wait_for_connection(&c).await;
let f = c.execute_query(&q).unwrap();
let r = f.await.unwrap();
assert_eq!(r.metadata.error, String::new());
assert_eq!(
r.metadata.query,
"test:\n return:\n type: literal\n datatype: \"http://www.w3.org/2001/XMLSchema#long\"\n value: 12\n"
);
assert!(r.metadata.success);
assert_eq!(r.head.vars, ["data"]);
assert_eq!(r.results.bindings.len(), 1);
let v0 = r.results.bindings.first().unwrap();
assert_eq!(v0.len(), 1);
let v0data = v0.get("data").unwrap();
assert_eq!(*v0data, 12.into());
}
#[tokio::test(flavor = "current_thread")]
async fn it_can_run_kd_query()
{
let mut store = crate::test::create_store(
crate::test::create_store_configuration()
.set_web_port(8888)
.load_extension("kDBDocuments"),
);
store.start().unwrap();
let c = crate::http::Connection::new("http://localhost:8888");
crate::test::wait_for_connection(&c).await;
let q = kdql::KDQLQuery::Create {
into: "test".into(),
documents: vec![
crate::krql_value_map!("name" => "a", "age" => 12),
crate::krql_value_map!("name" => "b", "age" => 42),
],
};
let f = c.execute_query(&q).unwrap();
let r = f.await.unwrap();
assert_eq!(r.metadata.error, String::new());
let q = kdql::KDQLQuery::Retrieve {
what: kdql::What::All,
from: "test".into(),
matches: crate::krql_value_map!("name" => "b"),
};
let f = c.execute_query(q).unwrap();
let r = f.await.unwrap();
assert_eq!(r.metadata.error, String::new());
assert!(r.metadata.success);
assert_eq!(r.head.vars, ["*"]);
assert_eq!(r.results.bindings.len(), 1);
let v0 = r.results.bindings.first().unwrap();
assert_eq!(v0.len(), 1);
let v0data = v0.get("*").unwrap();
assert_eq!(
*v0data,
crate::value_hash!("name" => "b", "age" => 42).into()
);
let q = kdql::KDQLQuery::Retrieve {
what: vec!["age"].into(),
from: "test".into(),
matches: crate::krql_value_map!("name" => "b"),
};
let f = c.execute_query(q).unwrap();
let r = f.await.unwrap();
assert_eq!(r.metadata.error, String::new());
assert!(r.metadata.success);
assert_eq!(r.head.vars, ["age"]);
assert_eq!(r.results.bindings.len(), 1);
let v0 = r.results.bindings.first().unwrap();
assert_eq!(v0.len(), 1);
let v0data = v0.get("age").unwrap();
assert_eq!(*v0data, 42.into());
}
}