use crate::api::Uni;
use std::collections::HashMap;
use uni_common::Result;
use uni_query::{ExecuteResult, QueryCursor, QueryResult, Row, Value};
#[must_use = "query builders do nothing until .fetch_all(), .fetch_one(), or .query_cursor() is called"]
pub struct QueryBuilder<'a> {
db: &'a Uni,
cypher: String,
params: HashMap<String, Value>,
timeout: Option<std::time::Duration>,
max_memory: Option<usize>,
}
impl<'a> QueryBuilder<'a> {
pub fn new(db: &'a Uni, cypher: &str) -> Self {
Self {
db,
cypher: cypher.to_string(),
params: HashMap::new(),
timeout: None,
max_memory: None,
}
}
pub fn timeout(mut self, duration: std::time::Duration) -> Self {
self.timeout = Some(duration);
self
}
pub fn max_memory(mut self, bytes: usize) -> Self {
self.max_memory = Some(bytes);
self
}
pub fn param(mut self, name: &str, value: impl Into<Value>) -> Self {
self.params.insert(name.to_string(), value.into());
self
}
pub fn params<'p>(mut self, params: impl IntoIterator<Item = (&'p str, Value)>) -> Self {
for (k, v) in params {
self.params.insert(k.to_string(), v);
}
self
}
pub async fn fetch_all(self) -> Result<QueryResult> {
let mut db_config = self.db.inner.config.clone();
if let Some(t) = self.timeout {
db_config.query_timeout = t;
}
if let Some(m) = self.max_memory {
db_config.max_query_memory = m;
}
self.db
.inner
.execute_internal_with_config(&self.cypher, self.params, db_config)
.await
}
pub async fn fetch_one(self) -> Result<Option<Row>> {
let result = self.fetch_all().await?;
Ok(result.into_rows().into_iter().next())
}
#[deprecated(
since = "0.4.0",
note = "Use `session.execute_with(cypher).run()` for auto-committed writes, or `fetch_all()` for queries"
)]
pub async fn execute(self) -> Result<ExecuteResult> {
let inner = &self.db.inner;
let before = inner.get_mutation_count().await;
let result = self.fetch_all().await?;
let affected_rows = if result.is_empty() {
inner.get_mutation_count().await.saturating_sub(before)
} else {
result.len()
};
Ok(ExecuteResult::new(affected_rows))
}
pub async fn query_cursor(self) -> Result<QueryCursor> {
let mut db_config = self.db.inner.config.clone();
if let Some(t) = self.timeout {
db_config.query_timeout = t;
}
if let Some(m) = self.max_memory {
db_config.max_query_memory = m;
}
self.db
.inner
.execute_cursor_internal_with_config(&self.cypher, self.params, db_config)
.await
}
}