uni_db/api/
query_builder.rs1use crate::api::Uni;
5use std::collections::HashMap;
6use uni_common::Result;
7use uni_query::{ExecuteResult, QueryCursor, QueryResult, Row, Value};
8
9#[must_use = "query builders do nothing until .fetch_all(), .fetch_one(), or .query_cursor() is called"]
28pub struct QueryBuilder<'a> {
29 db: &'a Uni,
30 cypher: String,
31 params: HashMap<String, Value>,
32 timeout: Option<std::time::Duration>,
33 max_memory: Option<usize>,
34}
35
36impl<'a> QueryBuilder<'a> {
37 pub fn new(db: &'a Uni, cypher: &str) -> Self {
38 Self {
39 db,
40 cypher: cypher.to_string(),
41 params: HashMap::new(),
42 timeout: None,
43 max_memory: None,
44 }
45 }
46
47 pub fn timeout(mut self, duration: std::time::Duration) -> Self {
50 self.timeout = Some(duration);
51 self
52 }
53
54 pub fn max_memory(mut self, bytes: usize) -> Self {
57 self.max_memory = Some(bytes);
58 self
59 }
60
61 pub fn param(mut self, name: &str, value: impl Into<Value>) -> Self {
65 self.params.insert(name.to_string(), value.into());
66 self
67 }
68
69 pub fn params<'p>(mut self, params: impl IntoIterator<Item = (&'p str, Value)>) -> Self {
71 for (k, v) in params {
72 self.params.insert(k.to_string(), v);
73 }
74 self
75 }
76
77 pub async fn fetch_all(self) -> Result<QueryResult> {
79 let mut db_config = self.db.inner.config.clone();
80 if let Some(t) = self.timeout {
81 db_config.query_timeout = t;
82 }
83 if let Some(m) = self.max_memory {
84 db_config.max_query_memory = m;
85 }
86
87 self.db
88 .inner
89 .execute_internal_with_config(&self.cypher, self.params, db_config)
90 .await
91 }
92
93 pub async fn fetch_one(self) -> Result<Option<Row>> {
95 let result = self.fetch_all().await?;
96 Ok(result.into_rows().into_iter().next())
97 }
98
99 #[deprecated(
101 since = "0.4.0",
102 note = "Use `session.execute_with(cypher).run()` for auto-committed writes, or `fetch_all()` for queries"
103 )]
104 pub async fn execute(self) -> Result<ExecuteResult> {
105 let inner = &self.db.inner;
106 let before = inner.get_mutation_count().await;
107 let result = self.fetch_all().await?;
108 let affected_rows = if result.is_empty() {
109 inner.get_mutation_count().await.saturating_sub(before)
110 } else {
111 result.len()
112 };
113 Ok(ExecuteResult::new(affected_rows))
114 }
115
116 pub async fn query_cursor(self) -> Result<QueryCursor> {
120 let mut db_config = self.db.inner.config.clone();
121 if let Some(t) = self.timeout {
122 db_config.query_timeout = t;
123 }
124 if let Some(m) = self.max_memory {
125 db_config.max_query_memory = m;
126 }
127
128 self.db
129 .inner
130 .execute_cursor_internal_with_config(&self.cypher, self.params, db_config)
131 .await
132 }
133}