Skip to main content

reifydb_transaction/transaction/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4//! Public `Transaction` handle. Wraps either a single-version or multi-version transaction body in a uniform
5//! shape so callers in the engine, planner, and policy layers do not branch on backend. Exposes the get/set/range
6//! primitives, delta accumulation, commit, the shape-resolution helpers, and the admin-only mutations the catalog
7//! tier needs.
8
9use std::sync::Arc;
10
11use reifydb_core::{
12	common::CommitVersion,
13	delta::Delta,
14	encoded::{
15		key::{EncodedKey, EncodedKeyRange},
16		row::EncodedRow,
17	},
18	execution::ExecutionResult,
19	interface::{
20		catalog::{policy::SessionOp, shape::ShapeId},
21		change::{Change, Diff},
22		store::{MultiVersionBatch, MultiVersionRow},
23	},
24	testing::{CapturedEvent, CapturedInvocation},
25	value::column::columns::Columns,
26};
27use reifydb_type::{
28	Result,
29	error::Diagnostic,
30	params::Params,
31	value::{datetime::DateTime, identity::IdentityId},
32};
33
34use crate::{
35	TransactionId,
36	change::{CatalogChangesSavepoint, RowChange},
37	interceptor::{
38		WithInterceptors,
39		authentication::{AuthenticationPostCreateInterceptor, AuthenticationPreDeleteInterceptor},
40		chain::InterceptorChain as Chain,
41		dictionary::{
42			DictionaryPostCreateInterceptor, DictionaryPostUpdateInterceptor,
43			DictionaryPreDeleteInterceptor, DictionaryPreUpdateInterceptor,
44		},
45		dictionary_row::{
46			DictionaryRowPostDeleteInterceptor, DictionaryRowPostInsertInterceptor,
47			DictionaryRowPostUpdateInterceptor, DictionaryRowPreDeleteInterceptor,
48			DictionaryRowPreInsertInterceptor, DictionaryRowPreUpdateInterceptor,
49		},
50		granted_role::{GrantedRolePostCreateInterceptor, GrantedRolePreDeleteInterceptor},
51		identity::{
52			IdentityPostCreateInterceptor, IdentityPostUpdateInterceptor, IdentityPreDeleteInterceptor,
53			IdentityPreUpdateInterceptor,
54		},
55		namespace::{
56			NamespacePostCreateInterceptor, NamespacePostUpdateInterceptor, NamespacePreDeleteInterceptor,
57			NamespacePreUpdateInterceptor,
58		},
59		ringbuffer::{
60			RingBufferPostCreateInterceptor, RingBufferPostUpdateInterceptor,
61			RingBufferPreDeleteInterceptor, RingBufferPreUpdateInterceptor,
62		},
63		ringbuffer_row::{
64			RingBufferRowPostDeleteInterceptor, RingBufferRowPostInsertInterceptor,
65			RingBufferRowPostUpdateInterceptor, RingBufferRowPreDeleteInterceptor,
66			RingBufferRowPreInsertInterceptor, RingBufferRowPreUpdateInterceptor,
67		},
68		role::{
69			RolePostCreateInterceptor, RolePostUpdateInterceptor, RolePreDeleteInterceptor,
70			RolePreUpdateInterceptor,
71		},
72		series::{
73			SeriesPostCreateInterceptor, SeriesPostUpdateInterceptor, SeriesPreDeleteInterceptor,
74			SeriesPreUpdateInterceptor,
75		},
76		series_row::{
77			SeriesRowPostDeleteInterceptor, SeriesRowPostInsertInterceptor, SeriesRowPostUpdateInterceptor,
78			SeriesRowPreDeleteInterceptor, SeriesRowPreInsertInterceptor, SeriesRowPreUpdateInterceptor,
79		},
80		table::{
81			TablePostCreateInterceptor, TablePostUpdateInterceptor, TablePreDeleteInterceptor,
82			TablePreUpdateInterceptor,
83		},
84		table_row::{
85			TableRowPostDeleteInterceptor, TableRowPostInsertInterceptor, TableRowPostUpdateInterceptor,
86			TableRowPreDeleteInterceptor, TableRowPreInsertInterceptor, TableRowPreUpdateInterceptor,
87		},
88		transaction::{PostCommitInterceptor, PreCommitContext, PreCommitInterceptor},
89		view::{
90			ViewPostCreateInterceptor, ViewPostUpdateInterceptor, ViewPreDeleteInterceptor,
91			ViewPreUpdateInterceptor,
92		},
93		view_row::{
94			ViewRowPostDeleteInterceptor, ViewRowPostInsertInterceptor, ViewRowPostUpdateInterceptor,
95			ViewRowPreDeleteInterceptor, ViewRowPreInsertInterceptor, ViewRowPreUpdateInterceptor,
96		},
97	},
98	multi::transaction::write::WriteSavepoint,
99	single::{read::SingleReadTransaction, write::SingleWriteTransaction},
100	transaction::{
101		admin::AdminTransaction, command::CommandTransaction, query::QueryTransaction,
102		replica::ReplicaTransaction, write::Write,
103	},
104};
105
106pub trait RqlExecutor: Send + Sync {
107	fn rql(&self, tx: &mut Transaction<'_>, rql: &str, params: Params) -> ExecutionResult;
108}
109
110pub mod admin;
111pub mod catalog;
112pub mod command;
113pub mod query;
114pub mod replica;
115pub mod write;
116
117use crate::multi::{pending::PendingWrites, transaction::write::MultiWriteTransaction};
118
119#[inline]
120pub(super) fn collect_transaction_writes(pending: &PendingWrites) -> Vec<(EncodedKey, Option<EncodedRow>)> {
121	pending.iter()
122		.map(|(key, p)| match &p.delta {
123			Delta::Set {
124				row,
125				..
126			} => (key.clone(), Some(row.clone())),
127			_ => (key.clone(), None),
128		})
129		.collect()
130}
131
132#[inline]
133pub(super) fn apply_pre_commit_writes(
134	multi: &mut MultiWriteTransaction,
135	pending_writes: &[(EncodedKey, Option<EncodedRow>)],
136) -> Result<()> {
137	for (key, value) in pending_writes {
138		match value {
139			Some(v) => multi.set(key, v.clone())?,
140			None => multi.remove(key)?,
141		}
142	}
143	Ok(())
144}
145
146pub struct Savepoint {
147	write: WriteSavepoint,
148	row_changes_len: usize,
149	accumulator_len: usize,
150	changes: CatalogChangesSavepoint,
151}
152
153pub struct TestTransaction<'a> {
154	pub inner: &'a mut AdminTransaction,
155	pub baseline: usize,
156	pub events: &'a mut Vec<CapturedEvent>,
157	pub invocations: &'a mut Vec<CapturedInvocation>,
158	pub event_seq: &'a mut u64,
159	pub handler_seq: &'a mut u64,
160	pub savepoint: Option<Savepoint>,
161	pub session_type: SessionOp,
162	pub session_default_deny: bool,
163}
164
165impl<'a> TestTransaction<'a> {
166	pub fn new(
167		inner: &'a mut AdminTransaction,
168		events: &'a mut Vec<CapturedEvent>,
169		invocations: &'a mut Vec<CapturedInvocation>,
170		event_seq: &'a mut u64,
171		handler_seq: &'a mut u64,
172		session_type: SessionOp,
173		session_default_deny: bool,
174	) -> Self {
175		let baseline = inner.accumulator.len();
176		let savepoint = Savepoint {
177			write: inner.cmd.as_ref().unwrap().savepoint(),
178			row_changes_len: inner.row_changes.len(),
179			accumulator_len: inner.accumulator.len(),
180			changes: inner.changes.savepoint(),
181		};
182		Self {
183			inner,
184			baseline,
185			events,
186			invocations,
187			event_seq,
188			handler_seq,
189			savepoint: Some(savepoint),
190			session_type,
191			session_default_deny,
192		}
193	}
194
195	pub fn restore(&mut self) {
196		if let Some(sp) = self.savepoint.take() {
197			self.inner.cmd.as_mut().unwrap().restore_savepoint(sp.write);
198			self.inner.row_changes.truncate(sp.row_changes_len);
199			self.inner.accumulator.truncate(sp.accumulator_len);
200			self.inner.changes.restore_savepoint(sp.changes);
201			self.inner.unpoison();
202		}
203	}
204
205	pub fn reborrow(&mut self) -> TestTransaction<'_> {
206		TestTransaction {
207			inner: &mut *self.inner,
208			baseline: self.baseline,
209			events: &mut *self.events,
210			invocations: &mut *self.invocations,
211			event_seq: &mut *self.event_seq,
212			handler_seq: &mut *self.handler_seq,
213			savepoint: None,
214			session_type: self.session_type,
215			session_default_deny: self.session_default_deny,
216		}
217	}
218
219	pub fn accumulator_entries_from(&self) -> &[(ShapeId, Diff)] {
220		self.inner.accumulator.entries_from(self.baseline)
221	}
222
223	pub fn capture_testing_pre_commit(&mut self) -> Result<()> {
224		let has_source_changes = self
225			.inner
226			.accumulator
227			.entries_from(self.baseline)
228			.iter()
229			.any(|(id, _)| !matches!(id, ShapeId::View(_)));
230
231		if !has_source_changes {
232			return Ok(());
233		}
234
235		let hook = self.inner.interceptors.test_pre_commit.clone();
236
237		if let Some(hook) = hook {
238			hook(self)?;
239		}
240
241		let offset = self.baseline;
242		let transaction_writes: Vec<(EncodedKey, Option<EncodedRow>)> = self
243			.inner
244			.pending_writes()
245			.iter()
246			.map(|(key, pending)| match &pending.delta {
247				Delta::Set {
248					row,
249					..
250				} => (key.clone(), Some(row.clone())),
251				_ => (key.clone(), None),
252			})
253			.collect();
254
255		let mut ctx = PreCommitContext {
256			flow_changes: self.inner.accumulator.take_changes_from(
257				offset,
258				CommitVersion(0),
259				DateTime::from_nanos(self.inner.clock.now_nanos()),
260			)?,
261			pending_writes: Vec::new(),
262			pending_shapes: Vec::new(),
263			transaction_writes,
264			view_entries: Vec::new(),
265		};
266
267		self.inner.interceptors.pre_commit.execute(&mut ctx)?;
268
269		for (key, value) in &ctx.pending_writes {
270			match value {
271				Some(v) => self.inner.cmd.as_mut().unwrap().set(key, v.clone())?,
272				None => self.inner.cmd.as_mut().unwrap().remove(key)?,
273			}
274		}
275
276		for (id, diff) in ctx.view_entries {
277			self.inner.accumulator.track(id, diff);
278		}
279
280		Ok(())
281	}
282}
283
284pub enum Transaction<'a> {
285	Command(&'a mut CommandTransaction),
286	Admin(&'a mut AdminTransaction),
287	Query(&'a mut QueryTransaction),
288	Test(Box<TestTransaction<'a>>),
289	Replica(&'a mut ReplicaTransaction),
290}
291
292impl<'a> Transaction<'a> {
293	pub fn version(&self) -> CommitVersion {
294		match self {
295			Self::Command(txn) => txn.version(),
296			Self::Admin(txn) => txn.version(),
297			Self::Query(txn) => txn.version(),
298			Self::Test(t) => t.inner.version(),
299			Self::Replica(txn) => txn.version(),
300		}
301	}
302
303	pub fn id(&self) -> TransactionId {
304		match self {
305			Self::Command(txn) => txn.id(),
306			Self::Admin(txn) => txn.id(),
307			Self::Query(txn) => txn.id(),
308			Self::Test(t) => t.inner.id(),
309			Self::Replica(txn) => txn.id(),
310		}
311	}
312
313	pub fn get(&mut self, key: &EncodedKey) -> Result<Option<MultiVersionRow>> {
314		match self {
315			Self::Command(txn) => txn.get(key),
316			Self::Admin(txn) => txn.get(key),
317			Self::Query(txn) => txn.get(key),
318			Self::Test(t) => t.inner.get(key),
319			Self::Replica(txn) => txn.get(key),
320		}
321	}
322
323	pub fn get_committed(&mut self, key: &EncodedKey) -> Result<Option<MultiVersionRow>> {
324		match self {
325			Self::Command(txn) => txn.get_committed(key),
326			Self::Admin(txn) => txn.get_committed(key),
327			Self::Query(txn) => txn.get(key),
328			Self::Test(t) => t.inner.get_committed(key),
329			Self::Replica(txn) => txn.get(key),
330		}
331	}
332
333	pub fn contains_key(&mut self, key: &EncodedKey) -> Result<bool> {
334		match self {
335			Self::Command(txn) => txn.contains_key(key),
336			Self::Admin(txn) => txn.contains_key(key),
337			Self::Query(txn) => txn.contains_key(key),
338			Self::Test(t) => t.inner.contains_key(key),
339			Self::Replica(txn) => txn.contains_key(key),
340		}
341	}
342
343	pub fn prefix(&mut self, prefix: &EncodedKey) -> Result<MultiVersionBatch> {
344		match self {
345			Self::Command(txn) => txn.prefix(prefix),
346			Self::Admin(txn) => txn.prefix(prefix),
347			Self::Query(txn) => txn.prefix(prefix),
348			Self::Test(t) => t.inner.prefix(prefix),
349			Self::Replica(txn) => txn.prefix(prefix),
350		}
351	}
352
353	pub fn prefix_rev(&mut self, prefix: &EncodedKey) -> Result<MultiVersionBatch> {
354		match self {
355			Self::Command(txn) => txn.prefix_rev(prefix),
356			Self::Admin(txn) => txn.prefix_rev(prefix),
357			Self::Query(txn) => txn.prefix_rev(prefix),
358			Self::Test(t) => t.inner.prefix_rev(prefix),
359			Self::Replica(txn) => txn.prefix_rev(prefix),
360		}
361	}
362
363	pub fn read_as_of_version_exclusive(&mut self, version: CommitVersion) -> Result<()> {
364		match self {
365			Transaction::Command(txn) => txn.read_as_of_version_exclusive(version),
366			Transaction::Admin(txn) => txn.read_as_of_version_exclusive(version),
367			Transaction::Query(txn) => txn.read_as_of_version_exclusive(version),
368			Transaction::Test(t) => t.inner.read_as_of_version_exclusive(version),
369			Transaction::Replica(_) => {
370				panic!("read_as_of_version_exclusive not supported on Replica transaction")
371			}
372		}
373	}
374
375	pub fn range(
376		&mut self,
377		range: EncodedKeyRange,
378		batch_size: usize,
379	) -> Result<Box<dyn Iterator<Item = Result<MultiVersionRow>> + Send + '_>> {
380		match self {
381			Transaction::Command(txn) => txn.range(range, batch_size),
382			Transaction::Admin(txn) => txn.range(range, batch_size),
383			Transaction::Query(txn) => Ok(txn.range(range, batch_size)),
384			Transaction::Test(t) => t.inner.range(range, batch_size),
385			Transaction::Replica(txn) => txn.range(range, batch_size),
386		}
387	}
388
389	pub fn range_rev(
390		&mut self,
391		range: EncodedKeyRange,
392		batch_size: usize,
393	) -> Result<Box<dyn Iterator<Item = Result<MultiVersionRow>> + Send + '_>> {
394		match self {
395			Transaction::Command(txn) => txn.range_rev(range, batch_size),
396			Transaction::Admin(txn) => txn.range_rev(range, batch_size),
397			Transaction::Query(txn) => Ok(txn.range_rev(range, batch_size)),
398			Transaction::Test(t) => t.inner.range_rev(range, batch_size),
399			Transaction::Replica(txn) => txn.range_rev(range, batch_size),
400		}
401	}
402}
403
404impl<'a> From<&'a mut CommandTransaction> for Transaction<'a> {
405	fn from(txn: &'a mut CommandTransaction) -> Self {
406		Self::Command(txn)
407	}
408}
409
410impl<'a> From<&'a mut AdminTransaction> for Transaction<'a> {
411	fn from(txn: &'a mut AdminTransaction) -> Self {
412		Self::Admin(txn)
413	}
414}
415
416impl<'a> From<&'a mut QueryTransaction> for Transaction<'a> {
417	fn from(txn: &'a mut QueryTransaction) -> Self {
418		Self::Query(txn)
419	}
420}
421
422impl<'a> From<&'a mut ReplicaTransaction> for Transaction<'a> {
423	fn from(txn: &'a mut ReplicaTransaction) -> Self {
424		Self::Replica(txn)
425	}
426}
427
428impl<'a> Transaction<'a> {
429	pub fn identity(&self) -> IdentityId {
430		match self {
431			Self::Command(txn) => txn.identity,
432			Self::Admin(txn) => txn.identity,
433			Self::Query(txn) => txn.identity,
434			Self::Test(t) => t.inner.identity,
435			Self::Replica(_) => IdentityId::system(),
436		}
437	}
438
439	pub fn set_identity(&mut self, identity: IdentityId) {
440		match self {
441			Self::Command(txn) => txn.identity = identity,
442			Self::Admin(txn) => txn.identity = identity,
443			Self::Query(txn) => txn.identity = identity,
444			Self::Test(t) => t.inner.identity = identity,
445			Self::Replica(_) => {}
446		}
447	}
448
449	fn executor_clone(&self) -> Option<Arc<dyn RqlExecutor>> {
450		match self {
451			Self::Command(txn) => txn.executor.clone(),
452			Self::Admin(txn) => txn.executor.clone(),
453			Self::Query(txn) => txn.executor.clone(),
454			Self::Test(t) => t.inner.executor.clone(),
455			Self::Replica(_) => None,
456		}
457	}
458
459	pub fn rql(&mut self, rql: &str, params: Params) -> ExecutionResult {
460		let executor = self.executor_clone().expect("RqlExecutor not set");
461		let mut tx = self.reborrow();
462		let result = executor.rql(&mut tx, rql, params);
463		if let Some(ref e) = result.error {
464			self.poison(*e.0.clone());
465		}
466		result
467	}
468
469	fn poison(&mut self, cause: Diagnostic) {
470		match self {
471			Transaction::Command(txn) => txn.poison(cause),
472			Transaction::Admin(txn) => txn.poison(cause),
473			Transaction::Query(_) => {}
474			Transaction::Test(t) => t.inner.poison(cause),
475			Transaction::Replica(_) => {}
476		}
477	}
478
479	pub fn reborrow(&mut self) -> Transaction<'_> {
480		match self {
481			Transaction::Command(cmd) => Transaction::Command(cmd),
482			Transaction::Admin(admin) => Transaction::Admin(admin),
483			Transaction::Query(qry) => Transaction::Query(qry),
484			Transaction::Test(t) => Transaction::Test(Box::new(TestTransaction {
485				inner: t.inner,
486				baseline: t.baseline,
487				events: t.events,
488				invocations: t.invocations,
489				event_seq: t.event_seq,
490				handler_seq: t.handler_seq,
491				savepoint: None,
492				session_type: t.session_type,
493				session_default_deny: t.session_default_deny,
494			})),
495			Transaction::Replica(rep) => Transaction::Replica(rep),
496		}
497	}
498
499	pub fn command(self) -> &'a mut CommandTransaction {
500		match self {
501			Self::Command(txn) => txn,
502			_ => panic!("Expected Command transaction"),
503		}
504	}
505
506	pub fn admin(self) -> &'a mut AdminTransaction {
507		match self {
508			Self::Admin(txn) => txn,
509			Self::Test(t) => t.inner,
510			_ => panic!("Expected Admin transaction"),
511		}
512	}
513
514	pub fn query(self) -> &'a mut QueryTransaction {
515		match self {
516			Self::Query(txn) => txn,
517			_ => panic!("Expected Query transaction"),
518		}
519	}
520
521	pub fn replica(self) -> &'a mut ReplicaTransaction {
522		match self {
523			Self::Replica(txn) => txn,
524			_ => panic!("Expected Replica transaction"),
525		}
526	}
527
528	pub fn command_mut(&mut self) -> &mut CommandTransaction {
529		match self {
530			Self::Command(txn) => txn,
531			_ => panic!("Expected Command transaction"),
532		}
533	}
534
535	pub fn admin_mut(&mut self) -> &mut AdminTransaction {
536		match self {
537			Self::Admin(txn) => txn,
538			Self::Test(t) => t.inner,
539			_ => panic!("Expected Admin transaction"),
540		}
541	}
542
543	pub fn query_mut(&mut self) -> &mut QueryTransaction {
544		match self {
545			Self::Query(txn) => txn,
546			_ => panic!("Expected Query transaction"),
547		}
548	}
549
550	pub fn replica_mut(&mut self) -> &mut ReplicaTransaction {
551		match self {
552			Self::Replica(txn) => txn,
553			_ => panic!("Expected Replica transaction"),
554		}
555	}
556
557	pub fn begin_single_query<'b, I>(&self, keys: I) -> Result<SingleReadTransaction<'_>>
558	where
559		I: IntoIterator<Item = &'b EncodedKey>,
560	{
561		match self {
562			Transaction::Command(txn) => txn.begin_single_query(keys),
563			Transaction::Admin(txn) => txn.begin_single_query(keys),
564			Transaction::Query(txn) => txn.begin_single_query(keys),
565			Transaction::Test(t) => t.inner.begin_single_query(keys),
566			Transaction::Replica(_) => panic!("Single queries not supported on Replica transaction"),
567		}
568	}
569
570	pub fn begin_single_command<'b, I>(&self, keys: I) -> Result<SingleWriteTransaction<'_>>
571	where
572		I: IntoIterator<Item = &'b EncodedKey>,
573	{
574		match self {
575			Transaction::Command(txn) => txn.begin_single_command(keys),
576			Transaction::Admin(txn) => txn.begin_single_command(keys),
577			Transaction::Query(_) => panic!("Write operations not supported on Query transaction"),
578			Transaction::Test(t) => t.inner.begin_single_command(keys),
579			Transaction::Replica(_) => panic!("Single commands not supported on Replica transaction"),
580		}
581	}
582
583	fn write_ops(&mut self) -> &mut dyn Write {
584		match self {
585			Transaction::Command(txn) => &mut **txn,
586			Transaction::Admin(txn) => &mut **txn,
587			Transaction::Query(_) => panic!("Write operations not supported on Query transaction"),
588			Transaction::Test(t) => &mut *t.inner,
589			Transaction::Replica(txn) => &mut **txn,
590		}
591	}
592
593	pub fn set(&mut self, key: &EncodedKey, row: EncodedRow) -> Result<()> {
594		Write::set(self.write_ops(), key, row)
595	}
596
597	pub fn unset(&mut self, key: &EncodedKey, row: EncodedRow) -> Result<()> {
598		Write::unset(self.write_ops(), key, row)
599	}
600
601	pub fn remove(&mut self, key: &EncodedKey) -> Result<()> {
602		Write::remove(self.write_ops(), key)
603	}
604
605	pub fn mark_preexisting(&mut self, key: &EncodedKey) -> Result<()> {
606		Write::mark_preexisting(self.write_ops(), key)
607	}
608
609	pub fn track_row_change(&mut self, changes: &[RowChange]) {
610		Write::track_row_change(self.write_ops(), changes)
611	}
612
613	pub fn track_flow_change(&mut self, change: Change) {
614		Write::track_flow_change(self.write_ops(), change)
615	}
616
617	pub fn record_test_event(
618		&mut self,
619		namespace: String,
620		event: String,
621		variant: String,
622		depth: u8,
623		columns: Columns,
624	) {
625		if let Transaction::Test(t) = self {
626			*t.event_seq += 1;
627			t.events.push(CapturedEvent {
628				sequence: *t.event_seq,
629				namespace,
630				event,
631				variant,
632				depth,
633				columns,
634			});
635		}
636	}
637
638	pub fn record_test_handler(&mut self, mut invocation: CapturedInvocation) {
639		if let Transaction::Test(t) = self {
640			*t.handler_seq += 1;
641			invocation.sequence = *t.handler_seq;
642			t.invocations.push(invocation);
643		}
644	}
645}
646
647macro_rules! delegate_interceptor {
648	($method:ident, $ret:ty) => {
649		fn $method(&mut self) -> $ret {
650			match self {
651				Transaction::Command(txn) => txn.$method(),
652				Transaction::Admin(txn) => txn.$method(),
653				Transaction::Query(_) => panic!("Interceptors not supported on Query transaction"),
654				Transaction::Test(t) => t.inner.$method(),
655				Transaction::Replica(_) => panic!("Interceptors not supported on Replica transaction"),
656			}
657		}
658	};
659}
660
661impl WithInterceptors for Transaction<'_> {
662	delegate_interceptor!(
663		table_row_pre_insert_interceptors,
664		&mut Chain<dyn TableRowPreInsertInterceptor + Send + Sync>
665	);
666	delegate_interceptor!(
667		table_row_post_insert_interceptors,
668		&mut Chain<dyn TableRowPostInsertInterceptor + Send + Sync>
669	);
670	delegate_interceptor!(
671		table_row_pre_update_interceptors,
672		&mut Chain<dyn TableRowPreUpdateInterceptor + Send + Sync>
673	);
674	delegate_interceptor!(
675		table_row_post_update_interceptors,
676		&mut Chain<dyn TableRowPostUpdateInterceptor + Send + Sync>
677	);
678	delegate_interceptor!(
679		table_row_pre_delete_interceptors,
680		&mut Chain<dyn TableRowPreDeleteInterceptor + Send + Sync>
681	);
682	delegate_interceptor!(
683		table_row_post_delete_interceptors,
684		&mut Chain<dyn TableRowPostDeleteInterceptor + Send + Sync>
685	);
686	delegate_interceptor!(
687		ringbuffer_row_pre_insert_interceptors,
688		&mut Chain<dyn RingBufferRowPreInsertInterceptor + Send + Sync>
689	);
690	delegate_interceptor!(
691		ringbuffer_row_post_insert_interceptors,
692		&mut Chain<dyn RingBufferRowPostInsertInterceptor + Send + Sync>
693	);
694	delegate_interceptor!(
695		ringbuffer_row_pre_update_interceptors,
696		&mut Chain<dyn RingBufferRowPreUpdateInterceptor + Send + Sync>
697	);
698	delegate_interceptor!(
699		ringbuffer_row_post_update_interceptors,
700		&mut Chain<dyn RingBufferRowPostUpdateInterceptor + Send + Sync>
701	);
702	delegate_interceptor!(
703		ringbuffer_row_pre_delete_interceptors,
704		&mut Chain<dyn RingBufferRowPreDeleteInterceptor + Send + Sync>
705	);
706	delegate_interceptor!(
707		ringbuffer_row_post_delete_interceptors,
708		&mut Chain<dyn RingBufferRowPostDeleteInterceptor + Send + Sync>
709	);
710	delegate_interceptor!(pre_commit_interceptors, &mut Chain<dyn PreCommitInterceptor + Send + Sync>);
711	delegate_interceptor!(post_commit_interceptors, &mut Chain<dyn PostCommitInterceptor + Send + Sync>);
712	delegate_interceptor!(
713		namespace_post_create_interceptors,
714		&mut Chain<dyn NamespacePostCreateInterceptor + Send + Sync>
715	);
716	delegate_interceptor!(
717		namespace_pre_update_interceptors,
718		&mut Chain<dyn NamespacePreUpdateInterceptor + Send + Sync>
719	);
720	delegate_interceptor!(
721		namespace_post_update_interceptors,
722		&mut Chain<dyn NamespacePostUpdateInterceptor + Send + Sync>
723	);
724	delegate_interceptor!(
725		namespace_pre_delete_interceptors,
726		&mut Chain<dyn NamespacePreDeleteInterceptor + Send + Sync>
727	);
728	delegate_interceptor!(table_post_create_interceptors, &mut Chain<dyn TablePostCreateInterceptor + Send + Sync>);
729	delegate_interceptor!(table_pre_update_interceptors, &mut Chain<dyn TablePreUpdateInterceptor + Send + Sync>);
730	delegate_interceptor!(table_post_update_interceptors, &mut Chain<dyn TablePostUpdateInterceptor + Send + Sync>);
731	delegate_interceptor!(table_pre_delete_interceptors, &mut Chain<dyn TablePreDeleteInterceptor + Send + Sync>);
732	delegate_interceptor!(
733		view_row_pre_insert_interceptors,
734		&mut Chain<dyn ViewRowPreInsertInterceptor + Send + Sync>
735	);
736	delegate_interceptor!(
737		view_row_post_insert_interceptors,
738		&mut Chain<dyn ViewRowPostInsertInterceptor + Send + Sync>
739	);
740	delegate_interceptor!(
741		view_row_pre_update_interceptors,
742		&mut Chain<dyn ViewRowPreUpdateInterceptor + Send + Sync>
743	);
744	delegate_interceptor!(
745		view_row_post_update_interceptors,
746		&mut Chain<dyn ViewRowPostUpdateInterceptor + Send + Sync>
747	);
748	delegate_interceptor!(
749		view_row_pre_delete_interceptors,
750		&mut Chain<dyn ViewRowPreDeleteInterceptor + Send + Sync>
751	);
752	delegate_interceptor!(
753		view_row_post_delete_interceptors,
754		&mut Chain<dyn ViewRowPostDeleteInterceptor + Send + Sync>
755	);
756	delegate_interceptor!(view_post_create_interceptors, &mut Chain<dyn ViewPostCreateInterceptor + Send + Sync>);
757	delegate_interceptor!(view_pre_update_interceptors, &mut Chain<dyn ViewPreUpdateInterceptor + Send + Sync>);
758	delegate_interceptor!(view_post_update_interceptors, &mut Chain<dyn ViewPostUpdateInterceptor + Send + Sync>);
759	delegate_interceptor!(view_pre_delete_interceptors, &mut Chain<dyn ViewPreDeleteInterceptor + Send + Sync>);
760	delegate_interceptor!(
761		ringbuffer_post_create_interceptors,
762		&mut Chain<dyn RingBufferPostCreateInterceptor + Send + Sync>
763	);
764	delegate_interceptor!(
765		ringbuffer_pre_update_interceptors,
766		&mut Chain<dyn RingBufferPreUpdateInterceptor + Send + Sync>
767	);
768	delegate_interceptor!(
769		ringbuffer_post_update_interceptors,
770		&mut Chain<dyn RingBufferPostUpdateInterceptor + Send + Sync>
771	);
772	delegate_interceptor!(
773		ringbuffer_pre_delete_interceptors,
774		&mut Chain<dyn RingBufferPreDeleteInterceptor + Send + Sync>
775	);
776	delegate_interceptor!(
777		dictionary_row_pre_insert_interceptors,
778		&mut Chain<dyn DictionaryRowPreInsertInterceptor + Send + Sync>
779	);
780	delegate_interceptor!(
781		dictionary_row_post_insert_interceptors,
782		&mut Chain<dyn DictionaryRowPostInsertInterceptor + Send + Sync>
783	);
784	delegate_interceptor!(
785		dictionary_row_pre_update_interceptors,
786		&mut Chain<dyn DictionaryRowPreUpdateInterceptor + Send + Sync>
787	);
788	delegate_interceptor!(
789		dictionary_row_post_update_interceptors,
790		&mut Chain<dyn DictionaryRowPostUpdateInterceptor + Send + Sync>
791	);
792	delegate_interceptor!(
793		dictionary_row_pre_delete_interceptors,
794		&mut Chain<dyn DictionaryRowPreDeleteInterceptor + Send + Sync>
795	);
796	delegate_interceptor!(
797		dictionary_row_post_delete_interceptors,
798		&mut Chain<dyn DictionaryRowPostDeleteInterceptor + Send + Sync>
799	);
800	delegate_interceptor!(
801		dictionary_post_create_interceptors,
802		&mut Chain<dyn DictionaryPostCreateInterceptor + Send + Sync>
803	);
804	delegate_interceptor!(
805		dictionary_pre_update_interceptors,
806		&mut Chain<dyn DictionaryPreUpdateInterceptor + Send + Sync>
807	);
808	delegate_interceptor!(
809		dictionary_post_update_interceptors,
810		&mut Chain<dyn DictionaryPostUpdateInterceptor + Send + Sync>
811	);
812	delegate_interceptor!(
813		dictionary_pre_delete_interceptors,
814		&mut Chain<dyn DictionaryPreDeleteInterceptor + Send + Sync>
815	);
816	delegate_interceptor!(
817		series_row_pre_insert_interceptors,
818		&mut Chain<dyn SeriesRowPreInsertInterceptor + Send + Sync>
819	);
820	delegate_interceptor!(
821		series_row_post_insert_interceptors,
822		&mut Chain<dyn SeriesRowPostInsertInterceptor + Send + Sync>
823	);
824	delegate_interceptor!(
825		series_row_pre_update_interceptors,
826		&mut Chain<dyn SeriesRowPreUpdateInterceptor + Send + Sync>
827	);
828	delegate_interceptor!(
829		series_row_post_update_interceptors,
830		&mut Chain<dyn SeriesRowPostUpdateInterceptor + Send + Sync>
831	);
832	delegate_interceptor!(
833		series_row_pre_delete_interceptors,
834		&mut Chain<dyn SeriesRowPreDeleteInterceptor + Send + Sync>
835	);
836	delegate_interceptor!(
837		series_row_post_delete_interceptors,
838		&mut Chain<dyn SeriesRowPostDeleteInterceptor + Send + Sync>
839	);
840	delegate_interceptor!(
841		series_post_create_interceptors,
842		&mut Chain<dyn SeriesPostCreateInterceptor + Send + Sync>
843	);
844	delegate_interceptor!(series_pre_update_interceptors, &mut Chain<dyn SeriesPreUpdateInterceptor + Send + Sync>);
845	delegate_interceptor!(
846		series_post_update_interceptors,
847		&mut Chain<dyn SeriesPostUpdateInterceptor + Send + Sync>
848	);
849	delegate_interceptor!(series_pre_delete_interceptors, &mut Chain<dyn SeriesPreDeleteInterceptor + Send + Sync>);
850	delegate_interceptor!(
851		identity_post_create_interceptors,
852		&mut Chain<dyn IdentityPostCreateInterceptor + Send + Sync>
853	);
854	delegate_interceptor!(
855		identity_pre_update_interceptors,
856		&mut Chain<dyn IdentityPreUpdateInterceptor + Send + Sync>
857	);
858	delegate_interceptor!(
859		identity_post_update_interceptors,
860		&mut Chain<dyn IdentityPostUpdateInterceptor + Send + Sync>
861	);
862	delegate_interceptor!(
863		identity_pre_delete_interceptors,
864		&mut Chain<dyn IdentityPreDeleteInterceptor + Send + Sync>
865	);
866	delegate_interceptor!(role_post_create_interceptors, &mut Chain<dyn RolePostCreateInterceptor + Send + Sync>);
867	delegate_interceptor!(role_pre_update_interceptors, &mut Chain<dyn RolePreUpdateInterceptor + Send + Sync>);
868	delegate_interceptor!(role_post_update_interceptors, &mut Chain<dyn RolePostUpdateInterceptor + Send + Sync>);
869	delegate_interceptor!(role_pre_delete_interceptors, &mut Chain<dyn RolePreDeleteInterceptor + Send + Sync>);
870	delegate_interceptor!(
871		granted_role_post_create_interceptors,
872		&mut Chain<dyn GrantedRolePostCreateInterceptor + Send + Sync>
873	);
874	delegate_interceptor!(
875		granted_role_pre_delete_interceptors,
876		&mut Chain<dyn GrantedRolePreDeleteInterceptor + Send + Sync>
877	);
878	delegate_interceptor!(
879		authentication_post_create_interceptors,
880		&mut Chain<dyn AuthenticationPostCreateInterceptor + Send + Sync>
881	);
882	delegate_interceptor!(
883		authentication_pre_delete_interceptors,
884		&mut Chain<dyn AuthenticationPreDeleteInterceptor + Send + Sync>
885	);
886}