use crate::error::Result;
use crate::sparql::{execute_query, parse_sparql, SparqlRequest, SparqlResponse};
use crate::state::AppState;
pub async fn execute(state: &AppState, req: SparqlRequest) -> Result<SparqlResponse> {
let start = std::time::Instant::now();
let parsed = parse_sparql(&req.query)?;
let graph = state.graph.read().await;
let result = execute_query(&graph, &parsed)?;
let execution_time_ms = start.elapsed().as_millis() as u64;
Ok(SparqlResponse {
result_type: result.result_type,
variables: result.variables,
bindings: result.bindings,
boolean: result.boolean,
triple_count: result.triple_count,
execution_time_ms,
})
}
#[cfg(test)]
mod tests {
use super::*;
use aingle_graph::{NodeId, Predicate, Triple, Value};
#[tokio::test]
async fn select_returns_inserted_data() {
let state = AppState::with_db_path(":memory:", None).unwrap();
{
let graph = state.graph.read().await;
graph
.insert(Triple::new(
NodeId::named("alice"),
Predicate::named("knows"),
Value::Node(NodeId::named("bob")),
))
.unwrap();
graph
.insert(Triple::new(
NodeId::named("alice"),
Predicate::named("name"),
Value::String("Alice".into()),
))
.unwrap();
}
let req = SparqlRequest {
query: "SELECT ?s ?p ?o WHERE { ?s ?p ?o }".to_string(),
default_graph: None,
named_graphs: None,
};
let resp = execute(&state, req).await.unwrap();
assert_eq!(resp.result_type, "bindings");
let bindings = resp.bindings.expect("SELECT should yield bindings");
assert_eq!(bindings.len(), 2);
}
#[tokio::test]
async fn select_on_empty_graph_succeeds() {
let state = AppState::with_db_path(":memory:", None).unwrap();
let req = SparqlRequest {
query: "SELECT ?s ?p ?o WHERE { ?s ?p ?o }".to_string(),
default_graph: None,
named_graphs: None,
};
let resp = execute(&state, req).await.unwrap();
assert_eq!(resp.result_type, "bindings");
assert!(resp.bindings.unwrap().is_empty());
}
}