Skip to main content

typedb_driver/
transaction.rs

1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements.  See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership.  The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License.  You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied.  See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20use std::{fmt, pin::Pin};
21
22use tracing::debug;
23
24use crate::{
25    Error, QueryOptions, TransactionOptions,
26    analyze::AnalyzedQuery,
27    answer::QueryAnswer,
28    common::{Promise, Result, TransactionType},
29    connection::TransactionStream,
30    given::GivenRows,
31};
32
33/// A transaction with a TypeDB database.
34pub struct Transaction {
35    /// The transaction’s type (READ or WRITE)
36    type_: TransactionType,
37    /// The options for the transaction
38    options: TransactionOptions,
39    transaction_stream: Pin<Box<TransactionStream>>,
40}
41
42impl Transaction {
43    pub(super) fn new(transaction_stream: TransactionStream) -> Self {
44        let transaction_stream = Box::pin(transaction_stream);
45        Transaction {
46            type_: transaction_stream.type_(),
47            options: transaction_stream.options().clone(),
48            transaction_stream,
49        }
50    }
51
52    /// Checks if the transaction is open.
53    ///
54    /// # Examples
55    ///
56    /// ```rust
57    /// transaction.is_open()
58    /// ```
59    pub fn is_open(&self) -> bool {
60        self.transaction_stream.is_open()
61    }
62
63    /// Performs a TypeQL query with default options.
64    /// See [`Transaction::query_with_options`]
65    ///
66    /// # Examples
67    ///
68    /// ```rust
69    /// transaction.query(query)
70    /// ```
71    pub fn query(&self, query: impl AsRef<str>) -> impl Promise<'static, Result<QueryAnswer>> {
72        self.query_with_options_and_rows(query, QueryOptions::new(), None)
73    }
74
75    /// Performs a TypeQL query in this transaction.
76    ///
77    /// # Arguments
78    ///
79    /// * `query` — The TypeQL query to be executed
80    /// * `options` — The QueryOptions to execute the query with
81    ///
82    /// # Examples
83    ///
84    /// ```rust
85    /// transaction.query_with_options(query, options)
86    /// ```
87    pub fn query_with_options(
88        &self,
89        query: impl AsRef<str>,
90        options: QueryOptions,
91    ) -> impl Promise<'static, Result<QueryAnswer>> {
92        self.query_with_options_and_rows(query, options, None)
93    }
94
95    /// Performs a TypeQL query in this transaction.
96    ///
97    /// # Arguments
98    ///
99    /// * `query` — The TypeQL query to be executed
100    /// * `rows` — The GivenRows to pass as input to the query.
101    ///
102    /// # Examples
103    ///
104    /// ```rust
105    /// transaction.query_with_options(query, options, rows)
106    /// ```
107    pub fn query_with_rows(
108        &self,
109        query: impl AsRef<str>,
110        rows: GivenRows,
111    ) -> impl Promise<'static, Result<QueryAnswer>> {
112        self.query_with_options_and_rows(query, QueryOptions::new(), Some(rows))
113    }
114
115    /// Performs a TypeQL query in this transaction.
116    ///
117    /// # Arguments
118    ///
119    /// * `query` — The TypeQL query to be executed
120    /// * `options` — The QueryOptions to execute the query with
121    /// * `rows` — The GivenRows to pass as input to the query.
122    ///
123    /// # Examples
124    ///
125    /// ```rust
126    /// transaction.query_with_options(query, options, rows)
127    /// ```
128    pub fn query_with_options_and_rows(
129        &self,
130        query: impl AsRef<str>,
131        options: QueryOptions,
132        rows: Option<GivenRows>,
133    ) -> impl Promise<'static, Result<QueryAnswer>> {
134        let query = query.as_ref();
135        debug!("Transaction submitting query: {}", query);
136        self.transaction_stream.query(query, options, rows)
137    }
138
139    /// Analyzes a TypeQL query in this transaction,
140    /// returning the translated structure & inferred types.
141    ///
142    /// # Arguments
143    ///
144    /// * `query` — The TypeQL query to be analyzed
145    ///
146    /// # Examples
147    ///
148    /// ```rust
149    /// transaction.analyze(query)
150    /// ```
151    pub fn analyze(&self, query: impl AsRef<str>) -> impl Promise<'static, Result<AnalyzedQuery>> {
152        self.transaction_stream.analyze(query.as_ref())
153    }
154
155    /// Retrieves the transaction’s type (READ or WRITE).
156    pub fn type_(&self) -> TransactionType {
157        self.type_
158    }
159
160    /// Registers a callback function which will be executed when this transaction is closed
161    /// returns a resolvable promise that must be awaited otherwise the callback may not be registered
162    ///
163    /// # Arguments
164    ///
165    /// * `function` — The callback function.
166    ///
167    /// # Examples
168    ///
169    /// ```rust
170    /// transaction.on_close(function)
171    /// ```
172    pub fn on_close(
173        &self,
174        callback: impl FnOnce(Option<Error>) + Send + Sync + 'static,
175    ) -> impl Promise<'_, Result<()>> {
176        self.transaction_stream.on_close(callback)
177    }
178
179    /// Closes the transaction and returns a resolvable promise
180    ///
181    /// # Examples
182    ///
183    /// ```rust
184    #[cfg_attr(feature = "sync", doc = "transaction.close().resolve()")]
185    #[cfg_attr(not(feature = "sync"), doc = "transaction.close().await")]
186    /// ```
187    pub fn close(&self) -> impl Promise<'_, Result<()>> {
188        self.transaction_stream.close()
189    }
190
191    /// Commits the changes made via this transaction to the TypeDB database. Whether or not the transaction is commited successfully, it gets closed after the commit call.
192    ///
193    /// # Examples
194    ///
195    /// ```rust
196    #[cfg_attr(feature = "sync", doc = "transaction.commit()")]
197    #[cfg_attr(not(feature = "sync"), doc = "transaction.commit().await")]
198    /// ```
199    pub fn commit(self) -> impl Promise<'static, Result> {
200        let stream = self.transaction_stream;
201        stream.commit()
202    }
203
204    /// Rolls back the uncommitted changes made via this transaction.
205    ///
206    /// # Examples
207    ///
208    /// ```rust
209    #[cfg_attr(feature = "sync", doc = "transaction.rollback()")]
210    #[cfg_attr(not(feature = "sync"), doc = "transaction.rollback().await")]
211    /// ```
212    pub fn rollback(&self) -> impl Promise<'_, Result> {
213        self.transaction_stream.rollback()
214    }
215}
216
217impl fmt::Debug for Transaction {
218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219        f.debug_struct("Transaction").field("type_", &self.type_).field("options", &self.options).finish()
220    }
221}