surrealdb_core/kvs/
tx.rs

1use super::batch::Batch;
2use super::tr::Check;
3use super::util;
4use super::Key;
5use super::KeyEncode;
6use super::Val;
7use super::Version;
8use crate::cnf::NORMAL_FETCH_SIZE;
9use crate::dbs::node::Node;
10use crate::err::Error;
11use crate::idx::trees::store::cache::IndexTreeCaches;
12use crate::kvs::cache;
13use crate::kvs::cache::tx::TransactionCache;
14use crate::kvs::scanner::Scanner;
15use crate::kvs::Transactor;
16use crate::sql::statements::define::ApiDefinition;
17use crate::sql::statements::define::DefineConfigStatement;
18use crate::sql::statements::AccessGrant;
19use crate::sql::statements::DefineAccessStatement;
20use crate::sql::statements::DefineAnalyzerStatement;
21use crate::sql::statements::DefineDatabaseStatement;
22use crate::sql::statements::DefineEventStatement;
23use crate::sql::statements::DefineFieldStatement;
24use crate::sql::statements::DefineFunctionStatement;
25use crate::sql::statements::DefineIndexStatement;
26use crate::sql::statements::DefineModelStatement;
27use crate::sql::statements::DefineNamespaceStatement;
28use crate::sql::statements::DefineParamStatement;
29use crate::sql::statements::DefineTableStatement;
30use crate::sql::statements::DefineUserStatement;
31use crate::sql::statements::LiveStatement;
32use crate::sql::Id;
33use crate::sql::Permissions;
34use crate::sql::Value;
35use futures::lock::Mutex;
36use futures::lock::MutexGuard;
37use futures::stream::Stream;
38use std::fmt::Debug;
39use std::ops::Range;
40use std::sync::Arc;
41use uuid::Uuid;
42
43#[non_exhaustive]
44pub struct Transaction {
45	/// Is this is a local datastore transaction
46	local: bool,
47	/// The underlying transactor
48	tx: Mutex<Transactor>,
49	/// The query cache for this store
50	cache: TransactionCache,
51	/// Cache the index updates
52	index_caches: IndexTreeCaches,
53}
54
55impl Transaction {
56	/// Create a new query store
57	pub fn new(local: bool, tx: Transactor) -> Transaction {
58		Transaction {
59			local,
60			tx: Mutex::new(tx),
61			cache: TransactionCache::new(),
62			index_caches: IndexTreeCaches::default(),
63		}
64	}
65
66	/// Retrieve the underlying transaction
67	pub fn inner(self) -> Transactor {
68		self.tx.into_inner()
69	}
70
71	/// Enclose this transaction in an [`Arc`]
72	pub fn enclose(self) -> Arc<Transaction> {
73		Arc::new(self)
74	}
75
76	/// Retrieve the underlying transaction
77	pub async fn lock(&self) -> MutexGuard<'_, Transactor> {
78		self.tx.lock().await
79	}
80
81	/// Check if the transaction is local or distributed
82	pub fn local(&self) -> bool {
83		self.local
84	}
85
86	/// Check if the transaction is finished.
87	///
88	/// If the transaction has been canceled or committed,
89	/// then this function will return [`true`], and any further
90	/// calls to functions on this transaction will result
91	/// in a [`Error::TxFinished`] error.
92	pub async fn closed(&self) -> bool {
93		self.lock().await.closed().await
94	}
95
96	/// Cancel a transaction.
97	///
98	/// This reverses all changes made within the transaction.
99	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
100	pub async fn cancel(&self) -> Result<(), Error> {
101		self.lock().await.cancel().await
102	}
103
104	/// Commit a transaction.
105	///
106	/// This attempts to commit all changes made within the transaction.
107	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
108	pub async fn commit(&self) -> Result<(), Error> {
109		self.lock().await.commit().await
110	}
111
112	/// Check if a key exists in the datastore.
113	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
114	pub async fn exists<K>(&self, key: K, version: Option<u64>) -> Result<bool, Error>
115	where
116		K: KeyEncode + Debug,
117	{
118		self.lock().await.exists(key, version).await
119	}
120
121	/// Fetch a key from the datastore.
122	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
123	pub async fn get<K>(&self, key: K, version: Option<u64>) -> Result<Option<Val>, Error>
124	where
125		K: KeyEncode + Debug,
126	{
127		self.lock().await.get(key, version).await
128	}
129
130	/// Retrieve a batch set of keys from the datastore.
131	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
132	pub async fn getm<K>(&self, keys: Vec<K>) -> Result<Vec<Option<Val>>, Error>
133	where
134		K: KeyEncode + Debug,
135	{
136		self.lock().await.getm(keys).await
137	}
138
139	/// Retrieve a specific prefix of keys from the datastore.
140	///
141	/// This function fetches key-value pairs from the underlying datastore in grouped batches.
142	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
143	pub async fn getp<K>(&self, key: K) -> Result<Vec<(Key, Val)>, Error>
144	where
145		K: KeyEncode + Debug,
146	{
147		self.lock().await.getp(key).await
148	}
149
150	/// Retrieve a specific range of keys from the datastore.
151	///
152	/// This function fetches key-value pairs from the underlying datastore in grouped batches.
153	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
154	pub async fn getr<K>(
155		&self,
156		rng: Range<K>,
157		version: Option<u64>,
158	) -> Result<Vec<(Key, Val)>, Error>
159	where
160		K: KeyEncode + Debug,
161	{
162		self.lock().await.getr(rng, version).await
163	}
164
165	/// Delete a key from the datastore.
166	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
167	pub async fn del<K>(&self, key: K) -> Result<(), Error>
168	where
169		K: KeyEncode + Debug,
170	{
171		self.lock().await.del(key).await
172	}
173
174	/// Delete a key from the datastore if the current value matches a condition.
175	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
176	pub async fn delc<K, V>(&self, key: K, chk: Option<V>) -> Result<(), Error>
177	where
178		K: KeyEncode + Debug,
179		V: Into<Val> + Debug,
180	{
181		self.lock().await.delc(key, chk).await
182	}
183
184	/// Delete a range of keys from the datastore.
185	///
186	/// This function deletes entries from the underlying datastore in grouped batches.
187	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
188	pub async fn delr<K>(&self, rng: Range<K>) -> Result<(), Error>
189	where
190		K: KeyEncode + Debug,
191	{
192		self.lock().await.delr(rng).await
193	}
194
195	/// Delete a prefix of keys from the datastore.
196	///
197	/// This function deletes entries from the underlying datastore in grouped batches.
198	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
199	pub async fn delp<K>(&self, key: K) -> Result<(), Error>
200	where
201		K: KeyEncode + Debug,
202	{
203		self.lock().await.delp(key).await
204	}
205
206	/// Delete all versions of a key from the datastore.
207	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
208	pub async fn clr<K>(&self, key: K) -> Result<(), Error>
209	where
210		K: KeyEncode + Debug,
211	{
212		self.lock().await.clr(key).await
213	}
214
215	/// Delete all versions of a key from the datastore if the current value matches a condition.
216	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
217	pub async fn clrc<K, V>(&self, key: K, chk: Option<V>) -> Result<(), Error>
218	where
219		K: KeyEncode + Debug,
220		V: Into<Val> + Debug,
221	{
222		self.lock().await.clrc(key, chk).await
223	}
224
225	/// Delete all versions of a range of keys from the datastore.
226	///
227	/// This function deletes entries from the underlying datastore in grouped batches.
228	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
229	pub async fn clrr<K>(&self, rng: Range<K>) -> Result<(), Error>
230	where
231		K: KeyEncode + Debug,
232	{
233		self.lock().await.clrr(rng).await
234	}
235
236	/// Delete all versions of a prefix of keys from the datastore.
237	///
238	/// This function deletes entries from the underlying datastore in grouped batches.
239	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
240	pub async fn clrp<K>(&self, key: K) -> Result<(), Error>
241	where
242		K: KeyEncode + Debug,
243	{
244		self.lock().await.clrp(key).await
245	}
246
247	/// Insert or update a key in the datastore.
248	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
249	pub async fn set<K, V>(&self, key: K, val: V, version: Option<u64>) -> Result<(), Error>
250	where
251		K: KeyEncode + Debug,
252		V: Into<Val> + Debug,
253	{
254		self.lock().await.set(key, val, version).await
255	}
256
257	/// Insert or replace a key in the datastore.
258	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
259	pub async fn replace<K, V>(&self, key: K, val: V) -> Result<(), Error>
260	where
261		K: KeyEncode + Debug,
262		V: Into<Val> + Debug,
263	{
264		self.lock().await.replace(key, val).await
265	}
266
267	/// Insert a key if it doesn't exist in the datastore.
268	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
269	pub async fn put<K, V>(&self, key: K, val: V, version: Option<u64>) -> Result<(), Error>
270	where
271		K: KeyEncode + Debug,
272		V: Into<Val> + Debug,
273	{
274		self.lock().await.put(key, val, version).await
275	}
276
277	/// Update a key in the datastore if the current value matches a condition.
278	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
279	pub async fn putc<K, V>(&self, key: K, val: V, chk: Option<V>) -> Result<(), Error>
280	where
281		K: KeyEncode + Debug,
282		V: Into<Val> + Debug,
283	{
284		self.lock().await.putc(key, val, chk).await
285	}
286
287	/// Retrieve a specific range of keys from the datastore.
288	///
289	/// This function fetches the full range of keys, in a single request to the underlying datastore.
290	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
291	pub async fn keys<K>(
292		&self,
293		rng: Range<K>,
294		limit: u32,
295		version: Option<u64>,
296	) -> Result<Vec<Key>, Error>
297	where
298		K: KeyEncode + Debug,
299	{
300		self.lock().await.keys(rng, limit, version).await
301	}
302
303	/// Retrieve a specific range of keys from the datastore.
304	///
305	/// This function fetches the full range of key-value pairs, in a single request to the underlying datastore.
306	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
307	pub async fn scan<K>(
308		&self,
309		rng: Range<K>,
310		limit: u32,
311		version: Option<u64>,
312	) -> Result<Vec<(Key, Val)>, Error>
313	where
314		K: KeyEncode + Debug,
315	{
316		self.lock().await.scan(rng, limit, version).await
317	}
318
319	/// Count the total number of keys within a range in the datastore.
320	///
321	/// This function fetches the total count, in batches, with multiple requests to the underlying datastore.
322	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
323	pub async fn count<K>(&self, rng: Range<K>) -> Result<usize, Error>
324	where
325		K: KeyEncode + Debug,
326	{
327		self.lock().await.count(rng).await
328	}
329
330	/// Retrieve a batched scan over a specific range of keys in the datastore.
331	///
332	/// This function fetches the keys in batches, with multiple requests to the underlying datastore.
333	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
334	pub async fn batch_keys<K>(
335		&self,
336		rng: Range<K>,
337		batch: u32,
338		version: Option<u64>,
339	) -> Result<Batch<Key>, Error>
340	where
341		K: KeyEncode + Debug,
342	{
343		self.lock().await.batch_keys(rng, batch, version).await
344	}
345
346	/// Retrieve a batched scan over a specific range of keys in the datastore.
347	///
348	/// This function fetches the key-value pairs in batches, with multiple requests to the underlying datastore.
349	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
350	pub async fn batch_keys_vals<K>(
351		&self,
352		rng: Range<K>,
353		batch: u32,
354		version: Option<u64>,
355	) -> Result<Batch<(Key, Val)>, Error>
356	where
357		K: KeyEncode + Debug,
358	{
359		self.lock().await.batch_keys_vals(rng, batch, version).await
360	}
361
362	/// Retrieve a batched scan over a specific range of keys in the datastore.
363	///
364	/// This function fetches the key-value-version pairs in batches, with multiple requests to the underlying datastore.
365	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
366	pub async fn batch_keys_vals_versions<K>(
367		&self,
368		rng: Range<K>,
369		batch: u32,
370	) -> Result<Batch<(Key, Val, Version, bool)>, Error>
371	where
372		K: KeyEncode + Debug,
373	{
374		self.lock().await.batch_keys_vals_versions(rng, batch).await
375	}
376
377	/// Retrieve a stream over a specific range of keys in the datastore.
378	///
379	/// This function fetches the key-value pairs in batches, with multiple requests to the underlying datastore.
380	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
381	pub fn stream(
382		&self,
383		rng: Range<Vec<u8>>,
384		version: Option<u64>,
385		limit: Option<usize>,
386	) -> impl Stream<Item = Result<(Key, Val), Error>> + '_ {
387		Scanner::<(Key, Val)>::new(self, *NORMAL_FETCH_SIZE, rng, version, limit)
388	}
389
390	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip_all)]
391	pub fn stream_keys(
392		&self,
393		rng: Range<Vec<u8>>,
394		limit: Option<usize>,
395	) -> impl Stream<Item = Result<Key, Error>> + '_ {
396		Scanner::<Key>::new(self, *NORMAL_FETCH_SIZE, rng, None, limit)
397	}
398
399	// --------------------------------------------------
400	// Rollback methods
401	// --------------------------------------------------
402
403	/// Warn if this transaction is dropped without proper handling.
404	pub async fn rollback_with_warning(self) -> Self {
405		self.tx.lock().await.check_level(Check::Warn);
406		self
407	}
408
409	/// Error if this transaction is dropped without proper handling.
410	pub async fn rollback_with_error(self) -> Self {
411		self.tx.lock().await.check_level(Check::Error);
412		self
413	}
414
415	/// Do nothing if this transaction is dropped without proper handling.
416	pub async fn rollback_and_ignore(self) -> Self {
417		self.tx.lock().await.check_level(Check::None);
418		self
419	}
420
421	// --------------------------------------------------
422	// Cache methods
423	// --------------------------------------------------
424
425	/// Retrieve all nodes belonging to this cluster.
426	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
427	pub async fn all_nodes(&self) -> Result<Arc<[Node]>, Error> {
428		let qey = cache::tx::Lookup::Nds;
429		match self.cache.get(&qey) {
430			Some(val) => val.try_into_nds(),
431			None => {
432				let beg = crate::key::root::nd::prefix();
433				let end = crate::key::root::nd::suffix();
434				let val = self.getr(beg..end, None).await?;
435				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
436				let entry = cache::tx::Entry::Nds(val.clone());
437				self.cache.insert(qey, entry);
438				Ok(val)
439			}
440		}
441	}
442
443	/// Retrieve all ROOT level users in a datastore.
444	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
445	pub async fn all_root_users(&self) -> Result<Arc<[DefineUserStatement]>, Error> {
446		let qey = cache::tx::Lookup::Rus;
447		match self.cache.get(&qey) {
448			Some(val) => val.try_into_rus(),
449			None => {
450				let beg = crate::key::root::us::prefix();
451				let end = crate::key::root::us::suffix();
452				let val = self.getr(beg..end, None).await?;
453				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
454				let entry = cache::tx::Entry::Rus(val.clone());
455				self.cache.insert(qey, entry);
456				Ok(val)
457			}
458		}
459	}
460
461	/// Retrieve all ROOT level accesses in a datastore.
462	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
463	pub async fn all_root_accesses(&self) -> Result<Arc<[DefineAccessStatement]>, Error> {
464		let qey = cache::tx::Lookup::Ras;
465		match self.cache.get(&qey) {
466			Some(val) => val.try_into_ras(),
467			None => {
468				let beg = crate::key::root::ac::prefix();
469				let end = crate::key::root::ac::suffix();
470				let val = self.getr(beg..end, None).await?;
471				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
472				let entry = cache::tx::Entry::Ras(val.clone());
473				self.cache.insert(qey, entry);
474				Ok(val)
475			}
476		}
477	}
478
479	/// Retrieve all root access grants in a datastore.
480	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
481	pub async fn all_root_access_grants(&self, ra: &str) -> Result<Arc<[AccessGrant]>, Error> {
482		let qey = cache::tx::Lookup::Rgs(ra);
483		match self.cache.get(&qey) {
484			Some(val) => val.try_into_rag(),
485			None => {
486				let beg = crate::key::root::access::gr::prefix(ra)?;
487				let end = crate::key::root::access::gr::suffix(ra)?;
488				let val = self.getr(beg..end, None).await?;
489				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
490				let entry = cache::tx::Entry::Rag(val.clone());
491				self.cache.insert(qey, entry);
492				Ok(val)
493			}
494		}
495	}
496
497	/// Retrieve all namespace definitions in a datastore.
498	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
499	pub async fn all_ns(&self) -> Result<Arc<[DefineNamespaceStatement]>, Error> {
500		let qey = cache::tx::Lookup::Nss;
501		match self.cache.get(&qey) {
502			Some(val) => val.try_into_nss(),
503			None => {
504				let beg = crate::key::root::ns::prefix();
505				let end = crate::key::root::ns::suffix();
506				let val = self.getr(beg..end, None).await?;
507				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
508				let entry = cache::tx::Entry::Nss(val.clone());
509				self.cache.insert(qey, entry);
510				Ok(val)
511			}
512		}
513	}
514
515	/// Retrieve all namespace user definitions for a specific namespace.
516	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
517	pub async fn all_ns_users(&self, ns: &str) -> Result<Arc<[DefineUserStatement]>, Error> {
518		let qey = cache::tx::Lookup::Nus(ns);
519		match self.cache.get(&qey) {
520			Some(val) => val.try_into_nus(),
521			None => {
522				let beg = crate::key::namespace::us::prefix(ns)?;
523				let end = crate::key::namespace::us::suffix(ns)?;
524				let val = self.getr(beg..end, None).await?;
525				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
526				let entry = cache::tx::Entry::Nus(val.clone());
527				self.cache.insert(qey, entry);
528				Ok(val)
529			}
530		}
531	}
532
533	/// Retrieve all namespace access definitions for a specific namespace.
534	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
535	pub async fn all_ns_accesses(&self, ns: &str) -> Result<Arc<[DefineAccessStatement]>, Error> {
536		let qey = cache::tx::Lookup::Nas(ns);
537		match self.cache.get(&qey) {
538			Some(val) => val.try_into_nas(),
539			None => {
540				let beg = crate::key::namespace::ac::prefix(ns)?;
541				let end = crate::key::namespace::ac::suffix(ns)?;
542				let val = self.getr(beg..end, None).await?;
543				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
544				let entry = cache::tx::Entry::Nas(val.clone());
545				self.cache.insert(qey, entry);
546				Ok(val)
547			}
548		}
549	}
550
551	/// Retrieve all namespace access grants for a specific namespace.
552	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
553	pub async fn all_ns_access_grants(
554		&self,
555		ns: &str,
556		na: &str,
557	) -> Result<Arc<[AccessGrant]>, Error> {
558		let qey = cache::tx::Lookup::Ngs(ns, na);
559		match self.cache.get(&qey) {
560			Some(val) => val.try_into_nag(),
561			None => {
562				let beg = crate::key::namespace::access::gr::prefix(ns, na)?;
563				let end = crate::key::namespace::access::gr::suffix(ns, na)?;
564				let val = self.getr(beg..end, None).await?;
565				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
566				let entry = cache::tx::Entry::Nag(val.clone());
567				self.cache.insert(qey, entry);
568				Ok(val)
569			}
570		}
571	}
572
573	/// Retrieve all database definitions for a specific namespace.
574	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
575	pub async fn all_db(&self, ns: &str) -> Result<Arc<[DefineDatabaseStatement]>, Error> {
576		let qey = cache::tx::Lookup::Dbs(ns);
577		match self.cache.get(&qey) {
578			Some(val) => val.try_into_dbs(),
579			None => {
580				let beg = crate::key::namespace::db::prefix(ns)?;
581				let end = crate::key::namespace::db::suffix(ns)?;
582				let val = self.getr(beg..end, None).await?;
583				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
584				let entry = cache::tx::Entry::Dbs(val.clone());
585				self.cache.insert(qey, entry);
586				Ok(val)
587			}
588		}
589	}
590
591	/// Retrieve all database user definitions for a specific database.
592	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
593	pub async fn all_db_users(
594		&self,
595		ns: &str,
596		db: &str,
597	) -> Result<Arc<[DefineUserStatement]>, Error> {
598		let qey = cache::tx::Lookup::Dus(ns, db);
599		match self.cache.get(&qey) {
600			Some(val) => val.try_into_dus(),
601			None => {
602				let beg = crate::key::database::us::prefix(ns, db)?;
603				let end = crate::key::database::us::suffix(ns, db)?;
604				let val = self.getr(beg..end, None).await?;
605				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
606				let entry = cache::tx::Entry::Dus(val.clone());
607				self.cache.insert(qey, entry);
608				Ok(val)
609			}
610		}
611	}
612
613	/// Retrieve all database access definitions for a specific database.
614	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
615	pub async fn all_db_accesses(
616		&self,
617		ns: &str,
618		db: &str,
619	) -> Result<Arc<[DefineAccessStatement]>, Error> {
620		let qey = cache::tx::Lookup::Das(ns, db);
621		match self.cache.get(&qey) {
622			Some(val) => val.try_into_das(),
623			None => {
624				let beg = crate::key::database::ac::prefix(ns, db)?;
625				let end = crate::key::database::ac::suffix(ns, db)?;
626				let val = self.getr(beg..end, None).await?;
627				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
628				let entry = cache::tx::Entry::Das(val.clone());
629				self.cache.insert(qey, entry);
630				Ok(val)
631			}
632		}
633	}
634
635	/// Retrieve all database access grants for a specific database.
636	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
637	pub async fn all_db_access_grants(
638		&self,
639		ns: &str,
640		db: &str,
641		da: &str,
642	) -> Result<Arc<[AccessGrant]>, Error> {
643		let qey = cache::tx::Lookup::Dgs(ns, db, da);
644		match self.cache.get(&qey) {
645			Some(val) => val.try_into_dag(),
646			None => {
647				let beg = crate::key::database::access::gr::prefix(ns, db, da)?;
648				let end = crate::key::database::access::gr::suffix(ns, db, da)?;
649				let val = self.getr(beg..end, None).await?;
650				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
651				let entry = cache::tx::Entry::Dag(val.clone());
652				self.cache.insert(qey, entry);
653				Ok(val)
654			}
655		}
656	}
657
658	/// Retrieve all api definitions for a specific database.
659	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
660	pub async fn all_db_apis(&self, ns: &str, db: &str) -> Result<Arc<[ApiDefinition]>, Error> {
661		let qey = cache::tx::Lookup::Aps(ns, db);
662		match self.cache.get(&qey) {
663			Some(val) => val,
664			None => {
665				let beg = crate::key::database::ap::prefix(ns, db)?;
666				let end = crate::key::database::ap::suffix(ns, db)?;
667				let val = self.getr(beg..end, None).await?;
668				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
669				let val = cache::tx::Entry::Aps(Arc::clone(&val));
670				self.cache.insert(qey, val.clone());
671				val
672			}
673		}
674		.try_into_aps()
675	}
676
677	/// Retrieve all analyzer definitions for a specific database.
678	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
679	pub async fn all_db_analyzers(
680		&self,
681		ns: &str,
682		db: &str,
683	) -> Result<Arc<[DefineAnalyzerStatement]>, Error> {
684		let qey = cache::tx::Lookup::Azs(ns, db);
685		match self.cache.get(&qey) {
686			Some(val) => val.try_into_azs(),
687			None => {
688				let beg = crate::key::database::az::prefix(ns, db)?;
689				let end = crate::key::database::az::suffix(ns, db)?;
690				let val = self.getr(beg..end, None).await?;
691				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
692				let entry = cache::tx::Entry::Azs(val.clone());
693				self.cache.insert(qey, entry);
694				Ok(val)
695			}
696		}
697	}
698
699	/// Retrieve all function definitions for a specific database.
700	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
701	pub async fn all_db_functions(
702		&self,
703		ns: &str,
704		db: &str,
705	) -> Result<Arc<[DefineFunctionStatement]>, Error> {
706		let qey = cache::tx::Lookup::Fcs(ns, db);
707		match self.cache.get(&qey) {
708			Some(val) => val.try_into_fcs(),
709			None => {
710				let beg = crate::key::database::fc::prefix(ns, db)?;
711				let end = crate::key::database::fc::suffix(ns, db)?;
712				let val = self.getr(beg..end, None).await?;
713				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
714				let entry = cache::tx::Entry::Fcs(val.clone());
715				self.cache.insert(qey, entry);
716				Ok(val)
717			}
718		}
719	}
720
721	/// Retrieve all param definitions for a specific database.
722	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
723	pub async fn all_db_params(
724		&self,
725		ns: &str,
726		db: &str,
727	) -> Result<Arc<[DefineParamStatement]>, Error> {
728		let qey = cache::tx::Lookup::Pas(ns, db);
729		match self.cache.get(&qey) {
730			Some(val) => val.try_into_pas(),
731			None => {
732				let beg = crate::key::database::pa::prefix(ns, db)?;
733				let end = crate::key::database::pa::suffix(ns, db)?;
734				let val = self.getr(beg..end, None).await?;
735				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
736				let entry = cache::tx::Entry::Pas(val.clone());
737				self.cache.insert(qey, entry);
738				Ok(val)
739			}
740		}
741	}
742
743	/// Retrieve all model definitions for a specific database.
744	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
745	pub async fn all_db_models(
746		&self,
747		ns: &str,
748		db: &str,
749	) -> Result<Arc<[DefineModelStatement]>, Error> {
750		let qey = cache::tx::Lookup::Mls(ns, db);
751		match self.cache.get(&qey) {
752			Some(val) => val.try_into_mls(),
753			None => {
754				let beg = crate::key::database::ml::prefix(ns, db)?;
755				let end = crate::key::database::ml::suffix(ns, db)?;
756				let val = self.getr(beg..end, None).await?;
757				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
758				let entry = cache::tx::Entry::Mls(val.clone());
759				self.cache.insert(qey, entry);
760				Ok(val)
761			}
762		}
763	}
764
765	/// Retrieve all model definitions for a specific database.
766	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
767	pub async fn all_db_configs(
768		&self,
769		ns: &str,
770		db: &str,
771	) -> Result<Arc<[DefineConfigStatement]>, Error> {
772		let qey = cache::tx::Lookup::Cgs(ns, db);
773		match self.cache.get(&qey) {
774			Some(val) => val.try_into_cgs(),
775			None => {
776				let beg = crate::key::database::cg::prefix(ns, db)?;
777				let end = crate::key::database::cg::suffix(ns, db)?;
778				let val = self.getr(beg..end, None).await?;
779				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
780				let entry = cache::tx::Entry::Cgs(val.clone());
781				self.cache.insert(qey, entry);
782				Ok(val)
783			}
784		}
785	}
786
787	/// Retrieve all table definitions for a specific database.
788	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
789	pub async fn all_tb(
790		&self,
791		ns: &str,
792		db: &str,
793		version: Option<u64>,
794	) -> Result<Arc<[DefineTableStatement]>, Error> {
795		let qey = cache::tx::Lookup::Tbs(ns, db);
796		match self.cache.get(&qey) {
797			Some(val) => val.try_into_tbs(),
798			None => {
799				let beg = crate::key::database::tb::prefix(ns, db)?;
800				let end = crate::key::database::tb::suffix(ns, db)?;
801				let val = self.getr(beg..end, version).await?;
802				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
803				let entry = cache::tx::Entry::Tbs(val.clone());
804				self.cache.insert(qey, entry);
805				Ok(val)
806			}
807		}
808	}
809
810	/// Retrieve all event definitions for a specific table.
811	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
812	pub async fn all_tb_events(
813		&self,
814		ns: &str,
815		db: &str,
816		tb: &str,
817	) -> Result<Arc<[DefineEventStatement]>, Error> {
818		let qey = cache::tx::Lookup::Evs(ns, db, tb);
819		match self.cache.get(&qey) {
820			Some(val) => val.try_into_evs(),
821			None => {
822				let beg = crate::key::table::ev::prefix(ns, db, tb)?;
823				let end = crate::key::table::ev::suffix(ns, db, tb)?;
824				let val = self.getr(beg..end, None).await?;
825				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
826				let entry = cache::tx::Entry::Evs(val.clone());
827				self.cache.insert(qey, entry);
828				Ok(val)
829			}
830		}
831	}
832
833	/// Retrieve all field definitions for a specific table.
834	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
835	pub async fn all_tb_fields(
836		&self,
837		ns: &str,
838		db: &str,
839		tb: &str,
840		version: Option<u64>,
841	) -> Result<Arc<[DefineFieldStatement]>, Error> {
842		let qey = cache::tx::Lookup::Fds(ns, db, tb);
843		match self.cache.get(&qey) {
844			Some(val) => val.try_into_fds(),
845			None => {
846				let beg = crate::key::table::fd::prefix(ns, db, tb)?;
847				let end = crate::key::table::fd::suffix(ns, db, tb)?;
848				let val = self.getr(beg..end, version).await?;
849				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
850				let entry = cache::tx::Entry::Fds(val.clone());
851				self.cache.insert(qey, entry);
852				Ok(val)
853			}
854		}
855	}
856
857	/// Retrieve all index definitions for a specific table.
858	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
859	pub async fn all_tb_indexes(
860		&self,
861		ns: &str,
862		db: &str,
863		tb: &str,
864	) -> Result<Arc<[DefineIndexStatement]>, Error> {
865		let qey = cache::tx::Lookup::Ixs(ns, db, tb);
866		match self.cache.get(&qey) {
867			Some(val) => val.try_into_ixs(),
868			None => {
869				let beg = crate::key::table::ix::prefix(ns, db, tb)?;
870				let end = crate::key::table::ix::suffix(ns, db, tb)?;
871				let val = self.getr(beg..end, None).await?;
872				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
873				let entry = cache::tx::Entry::Ixs(val.clone());
874				self.cache.insert(qey, entry);
875				Ok(val)
876			}
877		}
878	}
879
880	/// Retrieve all view definitions for a specific table.
881	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
882	pub async fn all_tb_views(
883		&self,
884		ns: &str,
885		db: &str,
886		tb: &str,
887	) -> Result<Arc<[DefineTableStatement]>, Error> {
888		let qey = cache::tx::Lookup::Fts(ns, db, tb);
889		match self.cache.get(&qey) {
890			Some(val) => val.try_into_fts(),
891			None => {
892				let beg = crate::key::table::ft::prefix(ns, db, tb)?;
893				let end = crate::key::table::ft::suffix(ns, db, tb)?;
894				let val = self.getr(beg..end, None).await?;
895				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
896				let entry = cache::tx::Entry::Fts(val.clone());
897				self.cache.insert(qey, entry);
898				Ok(val)
899			}
900		}
901	}
902
903	/// Retrieve all live definitions for a specific table.
904	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
905	pub async fn all_tb_lives(
906		&self,
907		ns: &str,
908		db: &str,
909		tb: &str,
910	) -> Result<Arc<[LiveStatement]>, Error> {
911		let qey = cache::tx::Lookup::Lvs(ns, db, tb);
912		match self.cache.get(&qey) {
913			Some(val) => val.try_into_lvs(),
914			None => {
915				let beg = crate::key::table::lq::prefix(ns, db, tb)?;
916				let end = crate::key::table::lq::suffix(ns, db, tb)?;
917				let val = self.getr(beg..end, None).await?;
918				let val = util::deserialize_cache(val.iter().map(|x| x.1.as_slice()))?;
919				let entry = cache::tx::Entry::Lvs(val.clone());
920				self.cache.insert(qey, entry);
921				Ok(val)
922			}
923		}
924	}
925
926	/// Retrieve a specific node in the cluster.
927	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
928	pub async fn get_node(&self, id: Uuid) -> Result<Arc<Node>, Error> {
929		let qey = cache::tx::Lookup::Nd(id);
930		match self.cache.get(&qey) {
931			Some(val) => val,
932			None => {
933				let key = crate::key::root::nd::new(id).encode()?;
934				let val = self.get(key, None).await?.ok_or_else(|| Error::NdNotFound {
935					uuid: id.to_string(),
936				})?;
937				let val: Node = revision::from_slice(&val)?;
938				let val = cache::tx::Entry::Any(Arc::new(val));
939				self.cache.insert(qey, val.clone());
940				val
941			}
942		}
943		.try_into_type()
944	}
945
946	/// Retrieve a specific root user definition.
947	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
948	pub async fn get_root_user(&self, us: &str) -> Result<Arc<DefineUserStatement>, Error> {
949		let qey = cache::tx::Lookup::Ru(us);
950		match self.cache.get(&qey) {
951			Some(val) => val.try_into_type(),
952			None => {
953				let key = crate::key::root::us::new(us).encode()?;
954				let val = self.get(key, None).await?.ok_or_else(|| Error::UserRootNotFound {
955					name: us.to_owned(),
956				})?;
957				let val: DefineUserStatement = revision::from_slice(&val)?;
958				let val = Arc::new(val);
959				let entr = cache::tx::Entry::Any(val.clone());
960				self.cache.insert(qey, entr);
961				Ok(val)
962			}
963		}
964	}
965
966	/// Retrieve a specific root access definition.
967	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
968	pub async fn get_root_access(&self, ra: &str) -> Result<Arc<DefineAccessStatement>, Error> {
969		let qey = cache::tx::Lookup::Ra(ra);
970		match self.cache.get(&qey) {
971			Some(val) => val.try_into_type(),
972			None => {
973				let key = crate::key::root::ac::new(ra).encode()?;
974				let val = self.get(key, None).await?.ok_or_else(|| Error::AccessRootNotFound {
975					ac: ra.to_owned(),
976				})?;
977				let val: DefineAccessStatement = revision::from_slice(&val)?;
978				let val = Arc::new(val);
979				let entr = cache::tx::Entry::Any(val.clone());
980				self.cache.insert(qey, entr);
981				Ok(val)
982			}
983		}
984	}
985
986	/// Retrieve a specific root access grant.
987	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
988	pub async fn get_root_access_grant(
989		&self,
990		ac: &str,
991		gr: &str,
992	) -> Result<Arc<AccessGrant>, Error> {
993		let qey = cache::tx::Lookup::Rg(ac, gr);
994		match self.cache.get(&qey) {
995			Some(val) => val.try_into_type(),
996			None => {
997				let key = crate::key::root::access::gr::new(ac, gr).encode()?;
998				let val =
999					self.get(key, None).await?.ok_or_else(|| Error::AccessGrantRootNotFound {
1000						ac: ac.to_owned(),
1001						gr: gr.to_owned(),
1002					})?;
1003				let val: AccessGrant = revision::from_slice(&val)?;
1004				let val = Arc::new(val);
1005				let entr = cache::tx::Entry::Any(val.clone());
1006				self.cache.insert(qey, entr);
1007				Ok(val)
1008			}
1009		}
1010	}
1011
1012	/// Retrieve a specific namespace definition.
1013	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1014	pub async fn get_ns(&self, ns: &str) -> Result<Arc<DefineNamespaceStatement>, Error> {
1015		let qey = cache::tx::Lookup::Ns(ns);
1016		match self.cache.get(&qey) {
1017			Some(val) => val.try_into_type(),
1018			None => {
1019				let key = crate::key::root::ns::new(ns).encode()?;
1020				let val = self.get(key, None).await?.ok_or_else(|| Error::NsNotFound {
1021					name: ns.to_owned(),
1022				})?;
1023				let val: DefineNamespaceStatement = revision::from_slice(&val)?;
1024				let val = Arc::new(val);
1025				let entr = cache::tx::Entry::Any(val.clone());
1026				self.cache.insert(qey, entr);
1027				Ok(val)
1028			}
1029		}
1030	}
1031
1032	/// Retrieve a specific namespace user definition.
1033	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1034	pub async fn get_ns_user(&self, ns: &str, us: &str) -> Result<Arc<DefineUserStatement>, Error> {
1035		let qey = cache::tx::Lookup::Nu(ns, us);
1036		match self.cache.get(&qey) {
1037			Some(val) => val.try_into_type(),
1038			None => {
1039				let key = crate::key::namespace::us::new(ns, us).encode()?;
1040				let val = self.get(key, None).await?.ok_or_else(|| Error::UserNsNotFound {
1041					name: us.to_owned(),
1042					ns: ns.to_owned(),
1043				})?;
1044				let val: DefineUserStatement = revision::from_slice(&val)?;
1045				let val = Arc::new(val);
1046				let entr = cache::tx::Entry::Any(val.clone());
1047				self.cache.insert(qey, entr);
1048				Ok(val)
1049			}
1050		}
1051	}
1052
1053	/// Retrieve a specific namespace access definition.
1054	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1055	pub async fn get_ns_access(
1056		&self,
1057		ns: &str,
1058		na: &str,
1059	) -> Result<Arc<DefineAccessStatement>, Error> {
1060		let qey = cache::tx::Lookup::Na(ns, na);
1061		match self.cache.get(&qey) {
1062			Some(val) => val.try_into_type(),
1063			None => {
1064				let key = crate::key::namespace::ac::new(ns, na).encode()?;
1065				let val = self.get(key, None).await?.ok_or_else(|| Error::AccessNsNotFound {
1066					ac: na.to_owned(),
1067					ns: ns.to_owned(),
1068				})?;
1069				let val: DefineAccessStatement = revision::from_slice(&val)?;
1070				let val = Arc::new(val);
1071				let entr = cache::tx::Entry::Any(val.clone());
1072				self.cache.insert(qey, entr);
1073				Ok(val)
1074			}
1075		}
1076	}
1077
1078	/// Retrieve a specific namespace access grant.
1079	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1080	pub async fn get_ns_access_grant(
1081		&self,
1082		ns: &str,
1083		ac: &str,
1084		gr: &str,
1085	) -> Result<Arc<AccessGrant>, Error> {
1086		let qey = cache::tx::Lookup::Ng(ns, ac, gr);
1087		match self.cache.get(&qey) {
1088			Some(val) => val.try_into_type(),
1089			None => {
1090				let key = crate::key::namespace::access::gr::new(ns, ac, gr).encode()?;
1091				let val =
1092					self.get(key, None).await?.ok_or_else(|| Error::AccessGrantNsNotFound {
1093						ac: ac.to_owned(),
1094						gr: gr.to_owned(),
1095						ns: ns.to_owned(),
1096					})?;
1097				let val: AccessGrant = revision::from_slice(&val)?;
1098				let val = Arc::new(val);
1099				let entr = cache::tx::Entry::Any(val.clone());
1100				self.cache.insert(qey, entr);
1101				Ok(val)
1102			}
1103		}
1104	}
1105
1106	/// Retrieve a specific database definition.
1107	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1108	pub async fn get_db(&self, ns: &str, db: &str) -> Result<Arc<DefineDatabaseStatement>, Error> {
1109		let qey = cache::tx::Lookup::Db(ns, db);
1110		match self.cache.get(&qey) {
1111			Some(val) => val.try_into_type(),
1112			None => {
1113				let key = crate::key::namespace::db::new(ns, db).encode()?;
1114				let val = self.get(key, None).await?.ok_or_else(|| Error::DbNotFound {
1115					name: db.to_owned(),
1116				})?;
1117				let val: DefineDatabaseStatement = revision::from_slice(&val)?;
1118				let val = Arc::new(val);
1119				let entr = cache::tx::Entry::Any(val.clone());
1120				self.cache.insert(qey, entr);
1121				Ok(val)
1122			}
1123		}
1124	}
1125
1126	/// Retrieve a specific user definition from a database.
1127	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1128	pub async fn get_db_user(
1129		&self,
1130		ns: &str,
1131		db: &str,
1132		us: &str,
1133	) -> Result<Arc<DefineUserStatement>, Error> {
1134		let qey = cache::tx::Lookup::Du(ns, db, us);
1135		match self.cache.get(&qey) {
1136			Some(val) => val.try_into_type(),
1137			None => {
1138				let key = crate::key::database::us::new(ns, db, us).encode()?;
1139				let val = self.get(key, None).await?.ok_or_else(|| Error::UserDbNotFound {
1140					name: us.to_owned(),
1141					ns: ns.to_owned(),
1142					db: db.to_owned(),
1143				})?;
1144				let val: DefineUserStatement = revision::from_slice(&val)?;
1145				let val = Arc::new(val);
1146				let entr = cache::tx::Entry::Any(val.clone());
1147				self.cache.insert(qey, entr);
1148				Ok(val)
1149			}
1150		}
1151	}
1152
1153	/// Retrieve a specific database access definition.
1154	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1155	pub async fn get_db_access(
1156		&self,
1157		ns: &str,
1158		db: &str,
1159		da: &str,
1160	) -> Result<Arc<DefineAccessStatement>, Error> {
1161		let qey = cache::tx::Lookup::Da(ns, db, da);
1162		match self.cache.get(&qey) {
1163			Some(val) => val.try_into_type(),
1164			None => {
1165				let key = crate::key::database::ac::new(ns, db, da).encode()?;
1166				let val = self.get(key, None).await?.ok_or_else(|| Error::AccessDbNotFound {
1167					ac: da.to_owned(),
1168					ns: ns.to_owned(),
1169					db: db.to_owned(),
1170				})?;
1171				let val: DefineAccessStatement = revision::from_slice(&val)?;
1172				let val = Arc::new(val);
1173				let entr = cache::tx::Entry::Any(val.clone());
1174				self.cache.insert(qey, entr);
1175				Ok(val)
1176			}
1177		}
1178	}
1179
1180	/// Retrieve a specific database access grant.
1181	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1182	pub async fn get_db_access_grant(
1183		&self,
1184		ns: &str,
1185		db: &str,
1186		ac: &str,
1187		gr: &str,
1188	) -> Result<Arc<AccessGrant>, Error> {
1189		let qey = cache::tx::Lookup::Dg(ns, db, ac, gr);
1190		match self.cache.get(&qey) {
1191			Some(val) => val.try_into_type(),
1192			None => {
1193				let key = crate::key::database::access::gr::new(ns, db, ac, gr).encode()?;
1194				let val =
1195					self.get(key, None).await?.ok_or_else(|| Error::AccessGrantDbNotFound {
1196						ac: ac.to_owned(),
1197						gr: gr.to_owned(),
1198						ns: ns.to_owned(),
1199						db: db.to_owned(),
1200					})?;
1201				let val: AccessGrant = revision::from_slice(&val)?;
1202				let val = Arc::new(val);
1203				let entr = cache::tx::Entry::Any(val.clone());
1204				self.cache.insert(qey, entr);
1205				Ok(val)
1206			}
1207		}
1208	}
1209
1210	/// Retrieve a specific model definition from a database.
1211	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1212	pub async fn get_db_model(
1213		&self,
1214		ns: &str,
1215		db: &str,
1216		ml: &str,
1217		vn: &str,
1218	) -> Result<Arc<DefineModelStatement>, Error> {
1219		let qey = cache::tx::Lookup::Ml(ns, db, ml, vn);
1220		match self.cache.get(&qey) {
1221			Some(val) => val.try_into_type(),
1222			None => {
1223				let key = crate::key::database::ml::new(ns, db, ml, vn).encode()?;
1224				let val = self.get(key, None).await?.ok_or_else(|| Error::MlNotFound {
1225					name: format!("{ml}<{vn}>"),
1226				})?;
1227				let val: DefineModelStatement = revision::from_slice(&val)?;
1228				let val = Arc::new(val);
1229				let entr = cache::tx::Entry::Any(val.clone());
1230				self.cache.insert(qey, entr);
1231				Ok(val)
1232			}
1233		}
1234	}
1235
1236	/// Retrieve a specific api definition.
1237	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1238	pub async fn get_db_api(
1239		&self,
1240		ns: &str,
1241		db: &str,
1242		ap: &str,
1243	) -> Result<Arc<ApiDefinition>, Error> {
1244		let qey = cache::tx::Lookup::Ap(ns, db, ap);
1245		match self.cache.get(&qey) {
1246			Some(val) => val,
1247			None => {
1248				let key = crate::key::database::ap::new(ns, db, ap).encode()?;
1249				let val = self.get(key, None).await?.ok_or_else(|| Error::ApNotFound {
1250					value: ap.to_owned(),
1251				})?;
1252				let val: ApiDefinition = revision::from_slice(&val)?;
1253				let val = cache::tx::Entry::Any(Arc::new(val));
1254				self.cache.insert(qey, val.clone());
1255				val
1256			}
1257		}
1258		.try_into_type()
1259	}
1260
1261	/// Retrieve a specific analyzer definition.
1262	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1263	pub async fn get_db_analyzer(
1264		&self,
1265		ns: &str,
1266		db: &str,
1267		az: &str,
1268	) -> Result<Arc<DefineAnalyzerStatement>, Error> {
1269		let qey = cache::tx::Lookup::Az(ns, db, az);
1270		match self.cache.get(&qey) {
1271			Some(val) => val.try_into_type(),
1272			None => {
1273				let key = crate::key::database::az::new(ns, db, az).encode()?;
1274				let val = self.get(key, None).await?.ok_or_else(|| Error::AzNotFound {
1275					name: az.to_owned(),
1276				})?;
1277				let val: DefineAnalyzerStatement = revision::from_slice(&val)?;
1278				let val = Arc::new(val);
1279				let entr = cache::tx::Entry::Any(val.clone());
1280				self.cache.insert(qey, entr);
1281				Ok(val)
1282			}
1283		}
1284	}
1285
1286	/// Retrieve a specific function definition from a database.
1287	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1288	pub async fn get_db_function(
1289		&self,
1290		ns: &str,
1291		db: &str,
1292		fc: &str,
1293	) -> Result<Arc<DefineFunctionStatement>, Error> {
1294		let qey = cache::tx::Lookup::Fc(ns, db, fc);
1295		match self.cache.get(&qey) {
1296			Some(val) => val.try_into_type(),
1297			None => {
1298				let key = crate::key::database::fc::new(ns, db, fc).encode()?;
1299				let val = self.get(key, None).await?.ok_or_else(|| Error::FcNotFound {
1300					name: fc.to_owned(),
1301				})?;
1302				let val: DefineFunctionStatement = revision::from_slice(&val)?;
1303				let val = Arc::new(val);
1304				let entr = cache::tx::Entry::Any(val.clone());
1305				self.cache.insert(qey, entr);
1306				Ok(val)
1307			}
1308		}
1309	}
1310
1311	/// Retrieve a specific function definition from a database.
1312	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1313	pub async fn get_db_param(
1314		&self,
1315		ns: &str,
1316		db: &str,
1317		pa: &str,
1318	) -> Result<Arc<DefineParamStatement>, Error> {
1319		let qey = cache::tx::Lookup::Pa(ns, db, pa);
1320		match self.cache.get(&qey) {
1321			Some(val) => val.try_into_type(),
1322			None => {
1323				let key = crate::key::database::pa::new(ns, db, pa).encode()?;
1324				let val = self.get(key, None).await?.ok_or_else(|| Error::PaNotFound {
1325					name: pa.to_owned(),
1326				})?;
1327				let val: DefineParamStatement = revision::from_slice(&val)?;
1328				let val = Arc::new(val);
1329				let entr = cache::tx::Entry::Any(val.clone());
1330				self.cache.insert(qey, entr);
1331				Ok(val)
1332			}
1333		}
1334	}
1335
1336	/// Retrieve a specific config definition from a database.
1337	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1338	pub async fn get_db_config(
1339		&self,
1340		ns: &str,
1341		db: &str,
1342		cg: &str,
1343	) -> Result<Arc<DefineConfigStatement>, Error> {
1344		if let Some(val) = self.get_db_optional_config(ns, db, cg).await? {
1345			Ok(val)
1346		} else {
1347			Err(Error::CgNotFound {
1348				name: cg.to_owned(),
1349			})
1350		}
1351	}
1352
1353	/// Retrieve a specific config definition from a database.
1354	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1355	pub async fn get_db_optional_config(
1356		&self,
1357		ns: &str,
1358		db: &str,
1359		cg: &str,
1360	) -> Result<Option<Arc<DefineConfigStatement>>, Error> {
1361		let qey = cache::tx::Lookup::Cg(ns, db, cg);
1362		match self.cache.get(&qey) {
1363			Some(val) => val.try_into_type().map(Option::Some),
1364			None => {
1365				let key = crate::key::database::cg::new(ns, db, cg).encode()?;
1366				if let Some(val) = self.get(key, None).await? {
1367					let val: DefineConfigStatement = revision::from_slice(&val)?;
1368					let val = Arc::new(val);
1369					let entr = cache::tx::Entry::Any(val.clone());
1370					self.cache.insert(qey, entr);
1371					Ok(Some(val))
1372				} else {
1373					Ok(None)
1374				}
1375			}
1376		}
1377	}
1378
1379	/// Retrieve a specific table definition.
1380	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1381	pub async fn get_tb(
1382		&self,
1383		ns: &str,
1384		db: &str,
1385		tb: &str,
1386	) -> Result<Arc<DefineTableStatement>, Error> {
1387		let qey = cache::tx::Lookup::Tb(ns, db, tb);
1388		match self.cache.get(&qey) {
1389			Some(val) => val.try_into_type(),
1390			None => {
1391				let key = crate::key::database::tb::new(ns, db, tb).encode()?;
1392				let val = self.get(key, None).await?.ok_or_else(|| Error::TbNotFound {
1393					name: tb.to_owned(),
1394				})?;
1395				let val: DefineTableStatement = revision::from_slice(&val)?;
1396				let val = Arc::new(val);
1397				let entr = cache::tx::Entry::Any(val.clone());
1398				self.cache.insert(qey, entr);
1399				Ok(val)
1400			}
1401		}
1402	}
1403
1404	/// Retrieve an event for a table.
1405	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1406	pub async fn get_tb_event(
1407		&self,
1408		ns: &str,
1409		db: &str,
1410		tb: &str,
1411		ev: &str,
1412	) -> Result<Arc<DefineEventStatement>, Error> {
1413		let qey = cache::tx::Lookup::Ev(ns, db, tb, ev);
1414		match self.cache.get(&qey) {
1415			Some(val) => val.try_into_type(),
1416			None => {
1417				let key = crate::key::table::ev::new(ns, db, tb, ev).encode()?;
1418				let val = self.get(key, None).await?.ok_or_else(|| Error::EvNotFound {
1419					name: ev.to_owned(),
1420				})?;
1421				let val: DefineEventStatement = revision::from_slice(&val)?;
1422				let val = Arc::new(val);
1423				let entr = cache::tx::Entry::Any(val.clone());
1424				self.cache.insert(qey, entr);
1425				Ok(val)
1426			}
1427		}
1428	}
1429
1430	/// Retrieve a field for a table.
1431	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1432	pub async fn get_tb_field(
1433		&self,
1434		ns: &str,
1435		db: &str,
1436		tb: &str,
1437		fd: &str,
1438	) -> Result<Arc<DefineFieldStatement>, Error> {
1439		let qey = cache::tx::Lookup::Fd(ns, db, tb, fd);
1440		match self.cache.get(&qey) {
1441			Some(val) => val.try_into_type(),
1442			None => {
1443				let key = crate::key::table::fd::new(ns, db, tb, fd).encode()?;
1444				let val = self.get(key, None).await?.ok_or_else(|| Error::FdNotFound {
1445					name: fd.to_owned(),
1446				})?;
1447				let val: DefineFieldStatement = revision::from_slice(&val)?;
1448				let val = Arc::new(val);
1449				let entr = cache::tx::Entry::Any(val.clone());
1450				self.cache.insert(qey, entr);
1451				Ok(val)
1452			}
1453		}
1454	}
1455
1456	/// Retrieve an index for a table.
1457	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1458	pub async fn get_tb_index(
1459		&self,
1460		ns: &str,
1461		db: &str,
1462		tb: &str,
1463		ix: &str,
1464	) -> Result<Arc<DefineIndexStatement>, Error> {
1465		let qey = cache::tx::Lookup::Ix(ns, db, tb, ix);
1466		match self.cache.get(&qey) {
1467			Some(val) => val.try_into_type(),
1468			None => {
1469				let key = crate::key::table::ix::new(ns, db, tb, ix).encode()?;
1470				let val = self.get(key, None).await?.ok_or_else(|| Error::IxNotFound {
1471					name: ix.to_owned(),
1472				})?;
1473				let val: DefineIndexStatement = revision::from_slice(&val)?;
1474				let val = Arc::new(val);
1475				let entr = cache::tx::Entry::Any(val.clone());
1476				self.cache.insert(qey, entr);
1477				Ok(val)
1478			}
1479		}
1480	}
1481
1482	/// Fetch a specific record value.
1483	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1484	pub async fn get_record(
1485		&self,
1486		ns: &str,
1487		db: &str,
1488		tb: &str,
1489		id: &Id,
1490		version: Option<u64>,
1491	) -> Result<Arc<Value>, Error> {
1492		// Cache is not versioned
1493		if version.is_some() {
1494			// Fetch the record from the datastore
1495			let key = crate::key::thing::new(ns, db, tb, id).encode()?;
1496			match self.get(key, version).await? {
1497				// The value exists in the datastore
1498				Some(val) => {
1499					let val = cache::tx::Entry::Val(Arc::new(revision::from_slice(&val)?));
1500					val.try_into_val()
1501				}
1502				// The value is not in the datastore
1503				None => Ok(Arc::new(Value::None)),
1504			}
1505		} else {
1506			let qey = cache::tx::Lookup::Record(ns, db, tb, id);
1507			match self.cache.get(&qey) {
1508				// The entry is in the cache
1509				Some(val) => val.try_into_val(),
1510				// The entry is not in the cache
1511				None => {
1512					// Fetch the record from the datastore
1513					let key = crate::key::thing::new(ns, db, tb, id).encode()?;
1514					match self.get(key, None).await? {
1515						// The value exists in the datastore
1516						Some(val) => {
1517							let val = cache::tx::Entry::Val(Arc::new(revision::from_slice(&val)?));
1518							self.cache.insert(qey, val.clone());
1519							val.try_into_val()
1520						}
1521						// The value is not in the datastore
1522						None => Ok(Arc::new(Value::None)),
1523					}
1524				}
1525			}
1526		}
1527	}
1528
1529	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1530	pub async fn set_record(
1531		&self,
1532		ns: &str,
1533		db: &str,
1534		tb: &str,
1535		id: &Id,
1536		val: Value,
1537	) -> Result<(), Error> {
1538		// Set the value in the datastore
1539		let key = crate::key::thing::new(ns, db, tb, id);
1540		self.set(&key, revision::to_vec(&val)?, None).await?;
1541		// Set the value in the cache
1542		let qey = cache::tx::Lookup::Record(ns, db, tb, id);
1543		self.cache.insert(qey, cache::tx::Entry::Val(Arc::new(val)));
1544		// Return nothing
1545		Ok(())
1546	}
1547
1548	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1549	pub fn set_record_cache(
1550		&self,
1551		ns: &str,
1552		db: &str,
1553		tb: &str,
1554		id: &Id,
1555		val: Arc<Value>,
1556	) -> Result<(), Error> {
1557		// Set the value in the cache
1558		let qey = cache::tx::Lookup::Record(ns, db, tb, id);
1559		self.cache.insert(qey, cache::tx::Entry::Val(val));
1560		// Return nothing
1561		Ok(())
1562	}
1563
1564	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1565	pub async fn del_record(&self, ns: &str, db: &str, tb: &str, id: &Id) -> Result<(), Error> {
1566		// Set the value in the datastore
1567		let key = crate::key::thing::new(ns, db, tb, id);
1568		self.del(&key).await?;
1569		// Set the value in the cache
1570		let qey = cache::tx::Lookup::Record(ns, db, tb, id);
1571		self.cache.remove(qey);
1572		// Return nothing
1573		Ok(())
1574	}
1575
1576	/// Get or add a namespace with a default configuration, only if we are in dynamic mode.
1577	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1578	pub async fn get_or_add_ns(
1579		&self,
1580		ns: &str,
1581		strict: bool,
1582	) -> Result<Arc<DefineNamespaceStatement>, Error> {
1583		self.get_or_add_ns_upwards(ns, strict, false).await
1584	}
1585
1586	/// Get or add a database with a default configuration, only if we are in dynamic mode.
1587	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1588	pub async fn get_or_add_db(
1589		&self,
1590		ns: &str,
1591		db: &str,
1592		strict: bool,
1593	) -> Result<Arc<DefineDatabaseStatement>, Error> {
1594		self.get_or_add_db_upwards(ns, db, strict, false).await
1595	}
1596
1597	/// Get or add a table with a default configuration, only if we are in dynamic mode.
1598	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1599	pub async fn get_or_add_tb(
1600		&self,
1601		ns: &str,
1602		db: &str,
1603		tb: &str,
1604		strict: bool,
1605	) -> Result<Arc<DefineTableStatement>, Error> {
1606		self.get_or_add_tb_upwards(ns, db, tb, strict, false).await
1607	}
1608
1609	/// Ensures that a table, database, and namespace are all fully defined.
1610	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1611	#[inline(always)]
1612	pub async fn ensure_ns_db_tb(
1613		&self,
1614		ns: &str,
1615		db: &str,
1616		tb: &str,
1617		strict: bool,
1618	) -> Result<Arc<DefineTableStatement>, Error> {
1619		self.get_or_add_tb_upwards(ns, db, tb, strict, true).await
1620	}
1621
1622	/// Ensure a specific table (and database, and namespace) exist.
1623	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1624	#[inline(always)]
1625	pub(crate) async fn check_ns_db_tb(
1626		&self,
1627		ns: &str,
1628		db: &str,
1629		tb: &str,
1630		strict: bool,
1631	) -> Result<(), Error> {
1632		match strict {
1633			// Strict mode is disabled
1634			false => Ok(()),
1635			// Strict mode is enabled
1636			true => {
1637				// Check that the table exists
1638				match self.get_tb(ns, db, tb).await {
1639					Err(Error::TbNotFound {
1640						name: tb,
1641					}) => {
1642						// If not, check the database exists
1643						match self.get_db(ns, db).await {
1644							Err(Error::DbNotFound {
1645								name: db,
1646							}) => {
1647								// If not, check the namespace exists
1648								match self.get_ns(ns).await {
1649									Err(Error::NsNotFound {
1650										name: ns,
1651									}) => Err(Error::NsNotFound {
1652										name: ns,
1653									}),
1654									// Return any other errors
1655									Err(err) => Err(err),
1656									// Namespace does exist
1657									Ok(_) => Err(Error::DbNotFound {
1658										name: db,
1659									}),
1660								}
1661							}
1662							// Return any other errors
1663							Err(err) => Err(err),
1664							// Database does exist
1665							Ok(_) => Err(Error::TbNotFound {
1666								name: tb,
1667							}),
1668						}
1669					}
1670					// Return any other errors
1671					Err(err) => Err(err),
1672					// Table does exist
1673					Ok(_) => Ok(()),
1674				}
1675			}
1676		}
1677	}
1678
1679	/// Clears all keys from the transaction cache.
1680	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1681	#[inline(always)]
1682	pub fn clear(&self) {
1683		self.cache.clear()
1684	}
1685
1686	// --------------------------------------------------
1687	// Private methods
1688	// --------------------------------------------------
1689
1690	/// Get or add a namespace with a default configuration, only if we are in dynamic mode.
1691	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1692	async fn get_or_add_ns_upwards(
1693		&self,
1694		ns: &str,
1695		strict: bool,
1696		_upwards: bool,
1697	) -> Result<Arc<DefineNamespaceStatement>, Error> {
1698		let qey = cache::tx::Lookup::Ns(ns);
1699		match self.cache.get(&qey) {
1700			// The entry is in the cache
1701			Some(val) => val,
1702			// The entry is not in the cache
1703			None => {
1704				// Try to fetch the value from the datastore
1705				let key = crate::key::root::ns::new(ns);
1706				let res = self.get(&key, None).await?.ok_or_else(|| Error::NsNotFound {
1707					name: ns.to_owned(),
1708				});
1709				// Check whether the value exists in the datastore
1710				match res {
1711					// Store a new default value in the datastore
1712					Err(Error::NsNotFound {
1713						..
1714					}) if !strict => {
1715						let val = DefineNamespaceStatement {
1716							name: ns.to_owned().into(),
1717							..Default::default()
1718						};
1719						let val = {
1720							self.put(&key, revision::to_vec(&val)?, None).await?;
1721							cache::tx::Entry::Any(Arc::new(val))
1722						};
1723						self.cache.insert(qey, val.clone());
1724						val
1725					}
1726					// Store the fetched value in the cache
1727					Ok(val) => {
1728						let val: DefineNamespaceStatement = revision::from_slice(&val)?;
1729						let val = cache::tx::Entry::Any(Arc::new(val));
1730						self.cache.insert(qey, val.clone());
1731						val
1732					}
1733					// Throw any received errors
1734					Err(err) => Err(err)?,
1735				}
1736			}
1737		}
1738		.try_into_type()
1739	}
1740
1741	/// Get or add a database with a default configuration, only if we are in dynamic mode.
1742	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1743	async fn get_or_add_db_upwards(
1744		&self,
1745		ns: &str,
1746		db: &str,
1747		strict: bool,
1748		upwards: bool,
1749	) -> Result<Arc<DefineDatabaseStatement>, Error> {
1750		let qey = cache::tx::Lookup::Db(ns, db);
1751		match self.cache.get(&qey) {
1752			// The entry is in the cache
1753			Some(val) => val,
1754			// The entry is not in the cache
1755			None => {
1756				// Try to fetch the value from the datastore
1757				let key = crate::key::namespace::db::new(ns, db);
1758				let res = self.get(&key, None).await?.ok_or_else(|| Error::DbNotFound {
1759					name: db.to_owned(),
1760				});
1761				// Check whether the value exists in the datastore
1762				match res {
1763					// Store a new default value in the datastore
1764					Err(Error::DbNotFound {
1765						..
1766					}) if !strict => {
1767						// First ensure that a namespace exists
1768						if upwards {
1769							self.get_or_add_ns_upwards(ns, strict, upwards).await?;
1770						}
1771						// Next, dynamically define the database
1772						let val = DefineDatabaseStatement {
1773							name: db.to_owned().into(),
1774							..Default::default()
1775						};
1776						let val = {
1777							self.put(&key, revision::to_vec(&val)?, None).await?;
1778							cache::tx::Entry::Any(Arc::new(val))
1779						};
1780						self.cache.insert(qey, val.clone());
1781						val
1782					}
1783					// Check to see that the hierarchy exists
1784					Err(Error::DbNotFound {
1785						name,
1786					}) if strict => {
1787						self.get_ns(ns).await?;
1788						Err(Error::DbNotFound {
1789							name,
1790						})?
1791					}
1792					// Store the fetched value in the cache
1793					Ok(val) => {
1794						let val: DefineDatabaseStatement = revision::from_slice(&val)?;
1795						let val = cache::tx::Entry::Any(Arc::new(val));
1796						self.cache.insert(qey, val.clone());
1797						val
1798					}
1799					// Throw any received errors
1800					Err(err) => Err(err)?,
1801				}
1802			}
1803		}
1804		.try_into_type()
1805	}
1806
1807	/// Get or add a table with a default configuration, only if we are in dynamic mode.
1808	#[instrument(level = "trace", target = "surrealdb::core::kvs::tx", skip(self))]
1809	async fn get_or_add_tb_upwards(
1810		&self,
1811		ns: &str,
1812		db: &str,
1813		tb: &str,
1814		strict: bool,
1815		upwards: bool,
1816	) -> Result<Arc<DefineTableStatement>, Error> {
1817		let qey = cache::tx::Lookup::Tb(ns, db, tb);
1818		match self.cache.get(&qey) {
1819			// The entry is in the cache
1820			Some(val) => val,
1821			// The entry is not in the cache
1822			None => {
1823				// Try to fetch the value from the datastore
1824				let key = crate::key::database::tb::new(ns, db, tb);
1825				let res = self.get(&key, None).await?.ok_or_else(|| Error::TbNotFound {
1826					name: tb.to_owned(),
1827				});
1828				// Check whether the value exists in the datastore
1829				match res {
1830					// Store a new default value in the datastore
1831					Err(Error::TbNotFound {
1832						..
1833					}) if !strict => {
1834						// First ensure that a database exists
1835						if upwards {
1836							self.get_or_add_db_upwards(ns, db, strict, upwards).await?;
1837						}
1838						// Next, dynamically define the table
1839						let val = DefineTableStatement {
1840							name: tb.to_owned().into(),
1841							permissions: Permissions::none(),
1842							..Default::default()
1843						};
1844						let val = {
1845							self.put(&key, revision::to_vec(&val)?, None).await?;
1846							cache::tx::Entry::Any(Arc::new(val))
1847						};
1848						self.cache.insert(qey, val.clone());
1849						val
1850					}
1851					// Check to see that the hierarchy exists
1852					Err(Error::TbNotFound {
1853						name,
1854					}) if strict => {
1855						self.get_ns(ns).await?;
1856						self.get_db(ns, db).await?;
1857						Err(Error::TbNotFound {
1858							name,
1859						})?
1860					}
1861					// Store the fetched value in the cache
1862					Ok(val) => {
1863						let val: DefineTableStatement = revision::from_slice(&val)?;
1864						let val = cache::tx::Entry::Any(Arc::new(val));
1865						self.cache.insert(qey, val.clone());
1866						val
1867					}
1868					// Throw any received errors
1869					Err(err) => Err(err)?,
1870				}
1871			}
1872		}
1873		.try_into_type()
1874	}
1875
1876	pub(crate) fn index_caches(&self) -> &IndexTreeCaches {
1877		&self.index_caches
1878	}
1879}