Skip to main content

reifydb_transaction/transaction/
admin.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::{mem::take, sync::Arc};
5
6use reifydb_core::{
7	common::CommitVersion,
8	encoded::{
9		key::{EncodedKey, EncodedKeyRange},
10		row::EncodedRow,
11	},
12	event::EventBus,
13	execution::ExecutionResult,
14	interface::{
15		WithEventBus,
16		change::{Change, ChangeOrigin},
17		store::{MultiVersionBatch, MultiVersionRow},
18	},
19};
20use reifydb_runtime::context::clock::Clock;
21use reifydb_type::{
22	Result,
23	error::Diagnostic,
24	params::Params,
25	value::{datetime::DateTime, identity::IdentityId},
26};
27use tracing::instrument;
28
29use crate::{
30	TransactionId,
31	change::{RowChange, TransactionalCatalogChanges, TransactionalChanges},
32	change_accumulator::ChangeAccumulator,
33	error::TransactionError,
34	interceptor::{
35		WithInterceptors,
36		authentication::{AuthenticationPostCreateInterceptor, AuthenticationPreDeleteInterceptor},
37		chain::InterceptorChain as Chain,
38		dictionary::{
39			DictionaryPostCreateInterceptor, DictionaryPostUpdateInterceptor,
40			DictionaryPreDeleteInterceptor, DictionaryPreUpdateInterceptor,
41		},
42		dictionary_row::{
43			DictionaryRowPostDeleteInterceptor, DictionaryRowPostInsertInterceptor,
44			DictionaryRowPostUpdateInterceptor, DictionaryRowPreDeleteInterceptor,
45			DictionaryRowPreInsertInterceptor, DictionaryRowPreUpdateInterceptor,
46		},
47		granted_role::{GrantedRolePostCreateInterceptor, GrantedRolePreDeleteInterceptor},
48		identity::{
49			IdentityPostCreateInterceptor, IdentityPostUpdateInterceptor, IdentityPreDeleteInterceptor,
50			IdentityPreUpdateInterceptor,
51		},
52		interceptors::Interceptors,
53		namespace::{
54			NamespacePostCreateInterceptor, NamespacePostUpdateInterceptor, NamespacePreDeleteInterceptor,
55			NamespacePreUpdateInterceptor,
56		},
57		ringbuffer::{
58			RingBufferPostCreateInterceptor, RingBufferPostUpdateInterceptor,
59			RingBufferPreDeleteInterceptor, RingBufferPreUpdateInterceptor,
60		},
61		ringbuffer_row::{
62			RingBufferRowPostDeleteInterceptor, RingBufferRowPostInsertInterceptor,
63			RingBufferRowPostUpdateInterceptor, RingBufferRowPreDeleteInterceptor,
64			RingBufferRowPreInsertInterceptor, RingBufferRowPreUpdateInterceptor,
65		},
66		role::{
67			RolePostCreateInterceptor, RolePostUpdateInterceptor, RolePreDeleteInterceptor,
68			RolePreUpdateInterceptor,
69		},
70		series::{
71			SeriesPostCreateInterceptor, SeriesPostUpdateInterceptor, SeriesPreDeleteInterceptor,
72			SeriesPreUpdateInterceptor,
73		},
74		series_row::{
75			SeriesRowPostDeleteInterceptor, SeriesRowPostInsertInterceptor, SeriesRowPostUpdateInterceptor,
76			SeriesRowPreDeleteInterceptor, SeriesRowPreInsertInterceptor, SeriesRowPreUpdateInterceptor,
77		},
78		table::{
79			TablePostCreateInterceptor, TablePostUpdateInterceptor, TablePreDeleteInterceptor,
80			TablePreUpdateInterceptor,
81		},
82		table_row::{
83			TableRowPostDeleteInterceptor, TableRowPostInsertInterceptor, TableRowPostUpdateInterceptor,
84			TableRowPreDeleteInterceptor, TableRowPreInsertInterceptor, TableRowPreUpdateInterceptor,
85		},
86		transaction::{PostCommitContext, PostCommitInterceptor, PreCommitContext, PreCommitInterceptor},
87		view::{
88			ViewPostCreateInterceptor, ViewPostUpdateInterceptor, ViewPreDeleteInterceptor,
89			ViewPreUpdateInterceptor,
90		},
91		view_row::{
92			ViewRowPostDeleteInterceptor, ViewRowPostInsertInterceptor, ViewRowPostUpdateInterceptor,
93			ViewRowPreDeleteInterceptor, ViewRowPreInsertInterceptor, ViewRowPreUpdateInterceptor,
94		},
95	},
96	multi::{
97		pending::PendingWrites,
98		transaction::{MultiTransaction, write::MultiWriteTransaction},
99	},
100	single::{SingleTransaction, read::SingleReadTransaction, write::SingleWriteTransaction},
101	transaction::{
102		RqlExecutor, Transaction, apply_pre_commit_writes, collect_transaction_writes, query::QueryTransaction,
103		write::Write,
104	},
105};
106
107pub struct AdminTransaction {
108	pub multi: MultiTransaction,
109	pub single: SingleTransaction,
110	state: TransactionState,
111
112	pub cmd: Option<MultiWriteTransaction>,
113	pub event_bus: EventBus,
114	pub changes: TransactionalCatalogChanges,
115
116	pub(crate) row_changes: Vec<RowChange>,
117	pub interceptors: Interceptors,
118
119	pub(crate) accumulator: ChangeAccumulator,
120
121	pub identity: IdentityId,
122
123	pub(crate) executor: Option<Arc<dyn RqlExecutor>>,
124
125	pub(crate) clock: Clock,
126
127	poison_cause: Option<Diagnostic>,
128}
129
130#[derive(Clone, Copy, PartialEq)]
131enum TransactionState {
132	Active,
133	Committed,
134	RolledBack,
135	Poisoned,
136}
137
138impl AdminTransaction {
139	#[instrument(name = "transaction::admin::new", level = "debug", skip_all)]
140	pub fn new(
141		multi: MultiTransaction,
142		single: SingleTransaction,
143		event_bus: EventBus,
144		interceptors: Interceptors,
145		identity: IdentityId,
146		clock: Clock,
147	) -> Result<Self> {
148		let cmd = multi.begin_command()?;
149		let txn_id = cmd.id();
150		Ok(Self {
151			cmd: Some(cmd),
152			multi,
153			single,
154			state: TransactionState::Active,
155			event_bus,
156			interceptors,
157			changes: TransactionalCatalogChanges::new(txn_id),
158			row_changes: Vec::new(),
159			accumulator: ChangeAccumulator::new(),
160			identity,
161			executor: None,
162			clock,
163			poison_cause: None,
164		})
165	}
166
167	pub fn set_executor(&mut self, executor: Arc<dyn RqlExecutor>) {
168		self.executor = Some(executor);
169	}
170
171	pub fn rql(&mut self, rql: &str, params: Params) -> ExecutionResult {
172		if let Err(e) = self.check_active() {
173			return ExecutionResult {
174				frames: vec![],
175				error: Some(e),
176				metrics: Default::default(),
177			};
178		}
179		let executor = self.executor.clone().expect("RqlExecutor not set");
180		let result = executor.rql(&mut Transaction::Admin(self), rql, params);
181		if let Some(ref e) = result.error {
182			self.poison(*e.0.clone());
183		}
184		result
185	}
186
187	#[instrument(name = "transaction::admin::event_bus", level = "trace", skip(self))]
188	pub fn event_bus(&self) -> &EventBus {
189		&self.event_bus
190	}
191
192	pub(crate) fn check_active(&self) -> Result<()> {
193		match self.state {
194			TransactionState::Active => Ok(()),
195			TransactionState::Committed => Err(TransactionError::AlreadyCommitted.into()),
196			TransactionState::RolledBack => Err(TransactionError::AlreadyRolledBack.into()),
197			TransactionState::Poisoned => Err(TransactionError::Poisoned {
198				cause: Box::new(self.poison_cause.clone().unwrap()),
199			}
200			.into()),
201		}
202	}
203
204	pub(crate) fn poison(&mut self, cause: Diagnostic) {
205		self.state = TransactionState::Poisoned;
206		self.poison_cause = Some(cause);
207	}
208
209	pub(crate) fn unpoison(&mut self) {
210		self.state = TransactionState::Active;
211		self.poison_cause = None;
212	}
213
214	#[instrument(name = "transaction::admin::commit", level = "debug", skip(self))]
215	pub fn commit(&mut self) -> Result<CommitVersion> {
216		self.check_active()?;
217		let mut ctx = self.build_pre_commit_context()?;
218		self.interceptors.pre_commit.execute(&mut ctx)?;
219		self.finalize_commit(ctx)
220	}
221
222	#[inline]
223	fn build_pre_commit_context(&mut self) -> Result<PreCommitContext> {
224		let transaction_writes = collect_transaction_writes(self.pending_writes());
225		Ok(PreCommitContext {
226			flow_changes: self
227				.accumulator
228				.take_changes(CommitVersion(0), DateTime::from_nanos(self.clock.now_nanos()))?,
229			pending_writes: Vec::new(),
230			pending_shapes: Vec::new(),
231			transaction_writes,
232			view_entries: Vec::new(),
233		})
234	}
235
236	fn finalize_commit(&mut self, ctx: PreCommitContext) -> Result<CommitVersion> {
237		let Some(mut multi) = self.cmd.take() else {
238			unreachable!("Transaction state inconsistency")
239		};
240		apply_pre_commit_writes(&mut multi, &ctx.pending_writes)?;
241		let id = multi.id();
242		self.state = TransactionState::Committed;
243
244		let changes = take(&mut self.changes);
245		let row_changes = take(&mut self.row_changes);
246		let version = multi.commit()?;
247		self.interceptors.post_commit.execute(PostCommitContext::new(id, version, changes, row_changes))?;
248		Ok(version)
249	}
250
251	#[instrument(name = "transaction::admin::rollback", level = "debug", skip(self))]
252	pub fn rollback(&mut self) -> Result<()> {
253		self.check_active()?;
254		if let Some(mut multi) = self.cmd.take() {
255			self.state = TransactionState::RolledBack;
256			multi.rollback()
257		} else {
258			unreachable!("Transaction state inconsistency")
259		}
260	}
261
262	#[instrument(name = "transaction::admin::pending_writes", level = "trace", skip(self))]
263	pub fn pending_writes(&self) -> &PendingWrites {
264		self.cmd.as_ref().unwrap().pending_writes()
265	}
266
267	#[instrument(name = "transaction::admin::with_single_query", level = "trace", skip(self, keys, f))]
268	pub fn with_single_query<'a, I, F, R>(&self, keys: I, f: F) -> Result<R>
269	where
270		I: IntoIterator<Item = &'a EncodedKey> + Send,
271		F: FnOnce(&mut SingleReadTransaction<'_>) -> Result<R> + Send,
272		R: Send,
273	{
274		self.check_active()?;
275		self.single.with_query(keys, f)
276	}
277
278	#[instrument(name = "transaction::admin::with_single_command", level = "trace", skip(self, keys, f))]
279	pub fn with_single_command<'a, I, F, R>(&self, keys: I, f: F) -> Result<R>
280	where
281		I: IntoIterator<Item = &'a EncodedKey> + Send,
282		F: FnOnce(&mut SingleWriteTransaction<'_>) -> Result<R> + Send,
283		R: Send,
284	{
285		self.check_active()?;
286		self.single.with_command(keys, f)
287	}
288
289	#[instrument(name = "transaction::admin::with_multi_query", level = "trace", skip(self, f))]
290	pub fn with_multi_query<F, R>(&self, f: F) -> Result<R>
291	where
292		F: FnOnce(&mut QueryTransaction) -> Result<R>,
293	{
294		self.check_active()?;
295
296		let mut query_txn =
297			QueryTransaction::new(self.multi.begin_query()?, self.single.clone(), self.identity);
298
299		f(&mut query_txn)
300	}
301
302	#[instrument(name = "transaction::admin::with_multi_query_as_of_exclusive", level = "trace", skip(self, f))]
303	pub fn with_multi_query_as_of_exclusive<F, R>(&self, version: CommitVersion, f: F) -> Result<R>
304	where
305		F: FnOnce(&mut QueryTransaction) -> Result<R>,
306	{
307		self.check_active()?;
308
309		let mut query_txn =
310			QueryTransaction::new(self.multi.begin_query()?, self.single.clone(), self.identity);
311
312		query_txn.read_as_of_version_exclusive(version)?;
313
314		f(&mut query_txn)
315	}
316
317	#[instrument(name = "transaction::admin::with_multi_query_as_of_inclusive", level = "trace", skip(self, f))]
318	pub fn with_multi_query_as_of_inclusive<F, R>(&self, version: CommitVersion, f: F) -> Result<R>
319	where
320		F: FnOnce(&mut QueryTransaction) -> Result<R>,
321	{
322		self.check_active()?;
323
324		let mut query_txn =
325			QueryTransaction::new(self.multi.begin_query()?, self.single.clone(), self.identity);
326
327		query_txn.multi.read_as_of_version_inclusive(version);
328
329		f(&mut query_txn)
330	}
331
332	#[instrument(name = "transaction::admin::begin_single_query", level = "trace", skip(self, keys))]
333	pub fn begin_single_query<'a, I>(&self, keys: I) -> Result<SingleReadTransaction<'_>>
334	where
335		I: IntoIterator<Item = &'a EncodedKey>,
336	{
337		self.check_active()?;
338		self.single.begin_query(keys)
339	}
340
341	#[instrument(name = "transaction::admin::begin_single_command", level = "trace", skip(self, keys))]
342	pub fn begin_single_command<'a, I>(&self, keys: I) -> Result<SingleWriteTransaction<'_>>
343	where
344		I: IntoIterator<Item = &'a EncodedKey>,
345	{
346		self.check_active()?;
347		self.single.begin_command(keys)
348	}
349
350	pub fn get_changes(&self) -> &TransactionalCatalogChanges {
351		&self.changes
352	}
353
354	pub fn track_row_change(&mut self, changes: &[RowChange]) {
355		self.row_changes.extend_from_slice(changes);
356	}
357
358	pub fn track_flow_change(&mut self, change: Change) {
359		if let ChangeOrigin::Shape(id) = change.origin {
360			for diff in change.diffs {
361				self.accumulator.track(id, diff);
362			}
363		}
364	}
365
366	#[inline]
367	pub fn version(&self) -> CommitVersion {
368		self.cmd.as_ref().unwrap().version()
369	}
370
371	#[inline]
372	pub fn id(&self) -> TransactionId {
373		self.cmd.as_ref().unwrap().id()
374	}
375
376	#[inline]
377	pub fn get(&mut self, key: &EncodedKey) -> Result<Option<MultiVersionRow>> {
378		self.check_active()?;
379		Ok(self.cmd.as_mut().unwrap().get(key)?.map(|v| v.into_multi_version_row()))
380	}
381
382	#[inline]
383	pub fn get_committed(&mut self, key: &EncodedKey) -> Result<Option<MultiVersionRow>> {
384		self.check_active()?;
385		Ok(self.cmd.as_mut().unwrap().get_committed(key)?.map(|v| v.into_multi_version_row()))
386	}
387
388	#[inline]
389	pub fn contains_key(&mut self, key: &EncodedKey) -> Result<bool> {
390		self.check_active()?;
391		self.cmd.as_mut().unwrap().contains_key(key)
392	}
393
394	#[inline]
395	pub fn prefix(&mut self, prefix: &EncodedKey) -> Result<MultiVersionBatch> {
396		self.check_active()?;
397		self.cmd.as_mut().unwrap().prefix(prefix)
398	}
399
400	#[inline]
401	pub fn prefix_rev(&mut self, prefix: &EncodedKey) -> Result<MultiVersionBatch> {
402		self.check_active()?;
403		self.cmd.as_mut().unwrap().prefix_rev(prefix)
404	}
405
406	#[inline]
407	pub fn read_as_of_version_exclusive(&mut self, version: CommitVersion) -> Result<()> {
408		self.check_active()?;
409		self.cmd.as_mut().unwrap().read_as_of_version_exclusive(version);
410		Ok(())
411	}
412
413	#[inline]
414	pub fn set(&mut self, key: &EncodedKey, row: EncodedRow) -> Result<()> {
415		self.check_active()?;
416		self.cmd.as_mut().unwrap().set(key, row)
417	}
418
419	#[inline]
420	pub fn unset(&mut self, key: &EncodedKey, row: EncodedRow) -> Result<()> {
421		self.check_active()?;
422		self.cmd.as_mut().unwrap().unset(key, row)
423	}
424
425	#[inline]
426	pub fn remove(&mut self, key: &EncodedKey) -> Result<()> {
427		self.check_active()?;
428		self.cmd.as_mut().unwrap().remove(key)
429	}
430
431	#[inline]
432	pub fn mark_preexisting(&mut self, key: &EncodedKey) -> Result<()> {
433		self.check_active()?;
434		self.cmd.as_mut().unwrap().mark_preexisting(key);
435		Ok(())
436	}
437
438	#[inline]
439	pub fn range(
440		&mut self,
441		range: EncodedKeyRange,
442		batch_size: usize,
443	) -> Result<Box<dyn Iterator<Item = Result<MultiVersionRow>> + Send + '_>> {
444		self.check_active()?;
445		Ok(self.cmd.as_mut().unwrap().range(range, batch_size))
446	}
447
448	#[inline]
449	pub fn range_rev(
450		&mut self,
451		range: EncodedKeyRange,
452		batch_size: usize,
453	) -> Result<Box<dyn Iterator<Item = Result<MultiVersionRow>> + Send + '_>> {
454		self.check_active()?;
455		Ok(self.cmd.as_mut().unwrap().range_rev(range, batch_size))
456	}
457}
458
459impl WithEventBus for AdminTransaction {
460	fn event_bus(&self) -> &EventBus {
461		&self.event_bus
462	}
463}
464
465impl Write for AdminTransaction {
466	#[inline]
467	fn set(&mut self, key: &EncodedKey, row: EncodedRow) -> Result<()> {
468		AdminTransaction::set(self, key, row)
469	}
470	#[inline]
471	fn unset(&mut self, key: &EncodedKey, row: EncodedRow) -> Result<()> {
472		AdminTransaction::unset(self, key, row)
473	}
474	#[inline]
475	fn remove(&mut self, key: &EncodedKey) -> Result<()> {
476		AdminTransaction::remove(self, key)
477	}
478	#[inline]
479	fn mark_preexisting(&mut self, key: &EncodedKey) -> Result<()> {
480		AdminTransaction::mark_preexisting(self, key)
481	}
482	#[inline]
483	fn track_row_change(&mut self, changes: &[RowChange]) {
484		AdminTransaction::track_row_change(self, changes)
485	}
486	#[inline]
487	fn track_flow_change(&mut self, change: Change) {
488		AdminTransaction::track_flow_change(self, change)
489	}
490}
491
492impl WithInterceptors for AdminTransaction {
493	fn table_row_pre_insert_interceptors(&mut self) -> &mut Chain<dyn TableRowPreInsertInterceptor + Send + Sync> {
494		&mut self.interceptors.table_row_pre_insert
495	}
496
497	fn table_row_post_insert_interceptors(
498		&mut self,
499	) -> &mut Chain<dyn TableRowPostInsertInterceptor + Send + Sync> {
500		&mut self.interceptors.table_row_post_insert
501	}
502
503	fn table_row_pre_update_interceptors(&mut self) -> &mut Chain<dyn TableRowPreUpdateInterceptor + Send + Sync> {
504		&mut self.interceptors.table_row_pre_update
505	}
506
507	fn table_row_post_update_interceptors(
508		&mut self,
509	) -> &mut Chain<dyn TableRowPostUpdateInterceptor + Send + Sync> {
510		&mut self.interceptors.table_row_post_update
511	}
512
513	fn table_row_pre_delete_interceptors(&mut self) -> &mut Chain<dyn TableRowPreDeleteInterceptor + Send + Sync> {
514		&mut self.interceptors.table_row_pre_delete
515	}
516
517	fn table_row_post_delete_interceptors(
518		&mut self,
519	) -> &mut Chain<dyn TableRowPostDeleteInterceptor + Send + Sync> {
520		&mut self.interceptors.table_row_post_delete
521	}
522
523	fn ringbuffer_row_pre_insert_interceptors(
524		&mut self,
525	) -> &mut Chain<dyn RingBufferRowPreInsertInterceptor + Send + Sync> {
526		&mut self.interceptors.ringbuffer_row_pre_insert
527	}
528
529	fn ringbuffer_row_post_insert_interceptors(
530		&mut self,
531	) -> &mut Chain<dyn RingBufferRowPostInsertInterceptor + Send + Sync> {
532		&mut self.interceptors.ringbuffer_row_post_insert
533	}
534
535	fn ringbuffer_row_pre_update_interceptors(
536		&mut self,
537	) -> &mut Chain<dyn RingBufferRowPreUpdateInterceptor + Send + Sync> {
538		&mut self.interceptors.ringbuffer_row_pre_update
539	}
540
541	fn ringbuffer_row_post_update_interceptors(
542		&mut self,
543	) -> &mut Chain<dyn RingBufferRowPostUpdateInterceptor + Send + Sync> {
544		&mut self.interceptors.ringbuffer_row_post_update
545	}
546
547	fn ringbuffer_row_pre_delete_interceptors(
548		&mut self,
549	) -> &mut Chain<dyn RingBufferRowPreDeleteInterceptor + Send + Sync> {
550		&mut self.interceptors.ringbuffer_row_pre_delete
551	}
552
553	fn ringbuffer_row_post_delete_interceptors(
554		&mut self,
555	) -> &mut Chain<dyn RingBufferRowPostDeleteInterceptor + Send + Sync> {
556		&mut self.interceptors.ringbuffer_row_post_delete
557	}
558
559	fn pre_commit_interceptors(&mut self) -> &mut Chain<dyn PreCommitInterceptor + Send + Sync> {
560		&mut self.interceptors.pre_commit
561	}
562
563	fn post_commit_interceptors(&mut self) -> &mut Chain<dyn PostCommitInterceptor + Send + Sync> {
564		&mut self.interceptors.post_commit
565	}
566
567	fn namespace_post_create_interceptors(
568		&mut self,
569	) -> &mut Chain<dyn NamespacePostCreateInterceptor + Send + Sync> {
570		&mut self.interceptors.namespace_post_create
571	}
572
573	fn namespace_pre_update_interceptors(&mut self) -> &mut Chain<dyn NamespacePreUpdateInterceptor + Send + Sync> {
574		&mut self.interceptors.namespace_pre_update
575	}
576
577	fn namespace_post_update_interceptors(
578		&mut self,
579	) -> &mut Chain<dyn NamespacePostUpdateInterceptor + Send + Sync> {
580		&mut self.interceptors.namespace_post_update
581	}
582
583	fn namespace_pre_delete_interceptors(&mut self) -> &mut Chain<dyn NamespacePreDeleteInterceptor + Send + Sync> {
584		&mut self.interceptors.namespace_pre_delete
585	}
586
587	fn table_post_create_interceptors(&mut self) -> &mut Chain<dyn TablePostCreateInterceptor + Send + Sync> {
588		&mut self.interceptors.table_post_create
589	}
590
591	fn table_pre_update_interceptors(&mut self) -> &mut Chain<dyn TablePreUpdateInterceptor + Send + Sync> {
592		&mut self.interceptors.table_pre_update
593	}
594
595	fn table_post_update_interceptors(&mut self) -> &mut Chain<dyn TablePostUpdateInterceptor + Send + Sync> {
596		&mut self.interceptors.table_post_update
597	}
598
599	fn table_pre_delete_interceptors(&mut self) -> &mut Chain<dyn TablePreDeleteInterceptor + Send + Sync> {
600		&mut self.interceptors.table_pre_delete
601	}
602
603	fn view_row_pre_insert_interceptors(&mut self) -> &mut Chain<dyn ViewRowPreInsertInterceptor + Send + Sync> {
604		&mut self.interceptors.view_row_pre_insert
605	}
606
607	fn view_row_post_insert_interceptors(&mut self) -> &mut Chain<dyn ViewRowPostInsertInterceptor + Send + Sync> {
608		&mut self.interceptors.view_row_post_insert
609	}
610
611	fn view_row_pre_update_interceptors(&mut self) -> &mut Chain<dyn ViewRowPreUpdateInterceptor + Send + Sync> {
612		&mut self.interceptors.view_row_pre_update
613	}
614
615	fn view_row_post_update_interceptors(&mut self) -> &mut Chain<dyn ViewRowPostUpdateInterceptor + Send + Sync> {
616		&mut self.interceptors.view_row_post_update
617	}
618
619	fn view_row_pre_delete_interceptors(&mut self) -> &mut Chain<dyn ViewRowPreDeleteInterceptor + Send + Sync> {
620		&mut self.interceptors.view_row_pre_delete
621	}
622
623	fn view_row_post_delete_interceptors(&mut self) -> &mut Chain<dyn ViewRowPostDeleteInterceptor + Send + Sync> {
624		&mut self.interceptors.view_row_post_delete
625	}
626
627	fn view_post_create_interceptors(&mut self) -> &mut Chain<dyn ViewPostCreateInterceptor + Send + Sync> {
628		&mut self.interceptors.view_post_create
629	}
630
631	fn view_pre_update_interceptors(&mut self) -> &mut Chain<dyn ViewPreUpdateInterceptor + Send + Sync> {
632		&mut self.interceptors.view_pre_update
633	}
634
635	fn view_post_update_interceptors(&mut self) -> &mut Chain<dyn ViewPostUpdateInterceptor + Send + Sync> {
636		&mut self.interceptors.view_post_update
637	}
638
639	fn view_pre_delete_interceptors(&mut self) -> &mut Chain<dyn ViewPreDeleteInterceptor + Send + Sync> {
640		&mut self.interceptors.view_pre_delete
641	}
642
643	fn ringbuffer_post_create_interceptors(
644		&mut self,
645	) -> &mut Chain<dyn RingBufferPostCreateInterceptor + Send + Sync> {
646		&mut self.interceptors.ringbuffer_post_create
647	}
648
649	fn ringbuffer_pre_update_interceptors(
650		&mut self,
651	) -> &mut Chain<dyn RingBufferPreUpdateInterceptor + Send + Sync> {
652		&mut self.interceptors.ringbuffer_pre_update
653	}
654
655	fn ringbuffer_post_update_interceptors(
656		&mut self,
657	) -> &mut Chain<dyn RingBufferPostUpdateInterceptor + Send + Sync> {
658		&mut self.interceptors.ringbuffer_post_update
659	}
660
661	fn ringbuffer_pre_delete_interceptors(
662		&mut self,
663	) -> &mut Chain<dyn RingBufferPreDeleteInterceptor + Send + Sync> {
664		&mut self.interceptors.ringbuffer_pre_delete
665	}
666
667	fn dictionary_row_pre_insert_interceptors(
668		&mut self,
669	) -> &mut Chain<dyn DictionaryRowPreInsertInterceptor + Send + Sync> {
670		&mut self.interceptors.dictionary_row_pre_insert
671	}
672
673	fn dictionary_row_post_insert_interceptors(
674		&mut self,
675	) -> &mut Chain<dyn DictionaryRowPostInsertInterceptor + Send + Sync> {
676		&mut self.interceptors.dictionary_row_post_insert
677	}
678
679	fn dictionary_row_pre_update_interceptors(
680		&mut self,
681	) -> &mut Chain<dyn DictionaryRowPreUpdateInterceptor + Send + Sync> {
682		&mut self.interceptors.dictionary_row_pre_update
683	}
684
685	fn dictionary_row_post_update_interceptors(
686		&mut self,
687	) -> &mut Chain<dyn DictionaryRowPostUpdateInterceptor + Send + Sync> {
688		&mut self.interceptors.dictionary_row_post_update
689	}
690
691	fn dictionary_row_pre_delete_interceptors(
692		&mut self,
693	) -> &mut Chain<dyn DictionaryRowPreDeleteInterceptor + Send + Sync> {
694		&mut self.interceptors.dictionary_row_pre_delete
695	}
696
697	fn dictionary_row_post_delete_interceptors(
698		&mut self,
699	) -> &mut Chain<dyn DictionaryRowPostDeleteInterceptor + Send + Sync> {
700		&mut self.interceptors.dictionary_row_post_delete
701	}
702
703	fn dictionary_post_create_interceptors(
704		&mut self,
705	) -> &mut Chain<dyn DictionaryPostCreateInterceptor + Send + Sync> {
706		&mut self.interceptors.dictionary_post_create
707	}
708
709	fn dictionary_pre_update_interceptors(
710		&mut self,
711	) -> &mut Chain<dyn DictionaryPreUpdateInterceptor + Send + Sync> {
712		&mut self.interceptors.dictionary_pre_update
713	}
714
715	fn dictionary_post_update_interceptors(
716		&mut self,
717	) -> &mut Chain<dyn DictionaryPostUpdateInterceptor + Send + Sync> {
718		&mut self.interceptors.dictionary_post_update
719	}
720
721	fn dictionary_pre_delete_interceptors(
722		&mut self,
723	) -> &mut Chain<dyn DictionaryPreDeleteInterceptor + Send + Sync> {
724		&mut self.interceptors.dictionary_pre_delete
725	}
726
727	fn series_row_pre_insert_interceptors(
728		&mut self,
729	) -> &mut Chain<dyn SeriesRowPreInsertInterceptor + Send + Sync> {
730		&mut self.interceptors.series_row_pre_insert
731	}
732
733	fn series_row_post_insert_interceptors(
734		&mut self,
735	) -> &mut Chain<dyn SeriesRowPostInsertInterceptor + Send + Sync> {
736		&mut self.interceptors.series_row_post_insert
737	}
738
739	fn series_row_pre_update_interceptors(
740		&mut self,
741	) -> &mut Chain<dyn SeriesRowPreUpdateInterceptor + Send + Sync> {
742		&mut self.interceptors.series_row_pre_update
743	}
744
745	fn series_row_post_update_interceptors(
746		&mut self,
747	) -> &mut Chain<dyn SeriesRowPostUpdateInterceptor + Send + Sync> {
748		&mut self.interceptors.series_row_post_update
749	}
750
751	fn series_row_pre_delete_interceptors(
752		&mut self,
753	) -> &mut Chain<dyn SeriesRowPreDeleteInterceptor + Send + Sync> {
754		&mut self.interceptors.series_row_pre_delete
755	}
756
757	fn series_row_post_delete_interceptors(
758		&mut self,
759	) -> &mut Chain<dyn SeriesRowPostDeleteInterceptor + Send + Sync> {
760		&mut self.interceptors.series_row_post_delete
761	}
762
763	fn series_post_create_interceptors(&mut self) -> &mut Chain<dyn SeriesPostCreateInterceptor + Send + Sync> {
764		&mut self.interceptors.series_post_create
765	}
766
767	fn series_pre_update_interceptors(&mut self) -> &mut Chain<dyn SeriesPreUpdateInterceptor + Send + Sync> {
768		&mut self.interceptors.series_pre_update
769	}
770
771	fn series_post_update_interceptors(&mut self) -> &mut Chain<dyn SeriesPostUpdateInterceptor + Send + Sync> {
772		&mut self.interceptors.series_post_update
773	}
774
775	fn series_pre_delete_interceptors(&mut self) -> &mut Chain<dyn SeriesPreDeleteInterceptor + Send + Sync> {
776		&mut self.interceptors.series_pre_delete
777	}
778
779	fn identity_post_create_interceptors(&mut self) -> &mut Chain<dyn IdentityPostCreateInterceptor + Send + Sync> {
780		&mut self.interceptors.identity_post_create
781	}
782
783	fn identity_pre_update_interceptors(&mut self) -> &mut Chain<dyn IdentityPreUpdateInterceptor + Send + Sync> {
784		&mut self.interceptors.identity_pre_update
785	}
786
787	fn identity_post_update_interceptors(&mut self) -> &mut Chain<dyn IdentityPostUpdateInterceptor + Send + Sync> {
788		&mut self.interceptors.identity_post_update
789	}
790
791	fn identity_pre_delete_interceptors(&mut self) -> &mut Chain<dyn IdentityPreDeleteInterceptor + Send + Sync> {
792		&mut self.interceptors.identity_pre_delete
793	}
794
795	fn role_post_create_interceptors(&mut self) -> &mut Chain<dyn RolePostCreateInterceptor + Send + Sync> {
796		&mut self.interceptors.role_post_create
797	}
798
799	fn role_pre_update_interceptors(&mut self) -> &mut Chain<dyn RolePreUpdateInterceptor + Send + Sync> {
800		&mut self.interceptors.role_pre_update
801	}
802
803	fn role_post_update_interceptors(&mut self) -> &mut Chain<dyn RolePostUpdateInterceptor + Send + Sync> {
804		&mut self.interceptors.role_post_update
805	}
806
807	fn role_pre_delete_interceptors(&mut self) -> &mut Chain<dyn RolePreDeleteInterceptor + Send + Sync> {
808		&mut self.interceptors.role_pre_delete
809	}
810
811	fn granted_role_post_create_interceptors(
812		&mut self,
813	) -> &mut Chain<dyn GrantedRolePostCreateInterceptor + Send + Sync> {
814		&mut self.interceptors.granted_role_post_create
815	}
816
817	fn granted_role_pre_delete_interceptors(
818		&mut self,
819	) -> &mut Chain<dyn GrantedRolePreDeleteInterceptor + Send + Sync> {
820		&mut self.interceptors.granted_role_pre_delete
821	}
822
823	fn authentication_post_create_interceptors(
824		&mut self,
825	) -> &mut Chain<dyn AuthenticationPostCreateInterceptor + Send + Sync> {
826		&mut self.interceptors.authentication_post_create
827	}
828
829	fn authentication_pre_delete_interceptors(
830		&mut self,
831	) -> &mut Chain<dyn AuthenticationPreDeleteInterceptor + Send + Sync> {
832		&mut self.interceptors.authentication_pre_delete
833	}
834}
835
836impl TransactionalChanges for AdminTransaction {}
837
838impl Drop for AdminTransaction {
839	fn drop(&mut self) {
840		if let Some(mut multi) = self.cmd.take()
841			&& (self.state == TransactionState::Active || self.state == TransactionState::Poisoned)
842		{
843			let _ = multi.rollback();
844		}
845	}
846}