uni_db/api/
query_builder.rs1use crate::api::Uni;
5use std::collections::HashMap;
6use uni_common::Result;
7use uni_query::{ExecuteResult, QueryCursor, QueryResult, Value};
8
9#[must_use = "query builders do nothing until .fetch_all(), .execute(), or .query_cursor() is called"]
27pub struct QueryBuilder<'a> {
28 db: &'a Uni,
29 cypher: String,
30 params: HashMap<String, Value>,
31 timeout: Option<std::time::Duration>,
32 max_memory: Option<usize>,
33}
34
35impl<'a> QueryBuilder<'a> {
36 pub fn new(db: &'a Uni, cypher: &str) -> Self {
37 Self {
38 db,
39 cypher: cypher.to_string(),
40 params: HashMap::new(),
41 timeout: None,
42 max_memory: None,
43 }
44 }
45
46 pub fn timeout(mut self, duration: std::time::Duration) -> Self {
49 self.timeout = Some(duration);
50 self
51 }
52
53 pub fn max_memory(mut self, bytes: usize) -> Self {
56 self.max_memory = Some(bytes);
57 self
58 }
59
60 pub fn param(mut self, name: &str, value: impl Into<Value>) -> Self {
64 self.params.insert(name.to_string(), value.into());
65 self
66 }
67
68 pub fn params<'p>(mut self, params: impl IntoIterator<Item = (&'p str, Value)>) -> Self {
70 for (k, v) in params {
71 self.params.insert(k.to_string(), v);
72 }
73 self
74 }
75
76 pub async fn fetch_all(self) -> Result<QueryResult> {
78 let mut db_config = self.db.config().clone();
79 if let Some(t) = self.timeout {
80 db_config.query_timeout = t;
81 }
82 if let Some(m) = self.max_memory {
83 db_config.max_query_memory = m;
84 }
85
86 self.db
87 .execute_internal_with_config(&self.cypher, self.params, db_config)
88 .await
89 }
90
91 pub async fn execute(self) -> Result<ExecuteResult> {
93 let db = self.db;
94 let before = db.get_mutation_count().await;
95 let result = self.fetch_all().await?;
96 let affected_rows = if result.is_empty() {
97 db.get_mutation_count().await.saturating_sub(before)
98 } else {
99 result.len()
100 };
101 Ok(ExecuteResult { affected_rows })
102 }
103
104 pub async fn query_cursor(self) -> Result<QueryCursor> {
108 let mut db_config = self.db.config().clone();
109 if let Some(t) = self.timeout {
110 db_config.query_timeout = t;
111 }
112 if let Some(m) = self.max_memory {
113 db_config.max_query_memory = m;
114 }
115
116 self.db
117 .execute_cursor_internal_with_config(&self.cypher, self.params, db_config)
118 .await
119 }
120}