use std::{ops::Bound, sync::Arc};
use reifydb_codec::{key::encoded::EncodedKey, row::bytes::EncodedBytes};
use reifydb_core::{
actors::pending::PendingWrite,
common::CommitVersion,
delta::{Delta, RemoveVisibility},
execution::ExecutionResult,
interface::{
catalog::{object::ObjectId, policy::SessionOp, storage::StorageId},
change::{Change, ChangeOrigin, Diff},
store::{MultiVersionBatch, MultiVersionRow},
},
key::{
any::TaggedKey,
bound::TaggedKeyBoundRange,
row::{StoragePartitionedRowKey, StorageRowKey},
},
testing::{CapturedEvent, CapturedInvocation},
value::column::columns::Columns,
};
use reifydb_value::{Result, error::Diagnostic, params::Params, value::identity::IdentityId};
use crate::{
TransactionId,
change::{CatalogChangesSavepoint, RowChange},
interceptor::{
WithInterceptors,
authentication::{AuthenticationPostCreateInterceptor, AuthenticationPreDeleteInterceptor},
chain::InterceptorChain as Chain,
dictionary::{
DictionaryPostCreateInterceptor, DictionaryPostUpdateInterceptor,
DictionaryPreDeleteInterceptor, DictionaryPreUpdateInterceptor,
},
dictionary_row::{
DictionaryRowPostDeleteInterceptor, DictionaryRowPostInsertInterceptor,
DictionaryRowPostUpdateInterceptor, DictionaryRowPreDeleteInterceptor,
DictionaryRowPreInsertInterceptor, DictionaryRowPreUpdateInterceptor,
},
granted_role::{GrantedRolePostCreateInterceptor, GrantedRolePreDeleteInterceptor},
identity::{IdentityPostCreateInterceptor, IdentityPreDeleteInterceptor},
identity_attribute::{IdentityAttributePostCreateInterceptor, IdentityAttributePreDeleteInterceptor},
identity_attribute_value::{
IdentityAttributeValuePostCreateInterceptor, IdentityAttributeValuePreDeleteInterceptor,
},
namespace::{
NamespacePostCreateInterceptor, NamespacePostUpdateInterceptor, NamespacePreDeleteInterceptor,
NamespacePreUpdateInterceptor,
},
ringbuffer::{
RingBufferPostCreateInterceptor, RingBufferPostUpdateInterceptor,
RingBufferPreDeleteInterceptor, RingBufferPreUpdateInterceptor,
},
ringbuffer_row::{
RingBufferRowPostDeleteInterceptor, RingBufferRowPostInsertInterceptor,
RingBufferRowPostUpdateInterceptor, RingBufferRowPreDeleteInterceptor,
RingBufferRowPreInsertInterceptor, RingBufferRowPreUpdateInterceptor,
},
role::{RolePostCreateInterceptor, RolePreDeleteInterceptor},
series::{
SeriesPostCreateInterceptor, SeriesPostUpdateInterceptor, SeriesPreDeleteInterceptor,
SeriesPreUpdateInterceptor,
},
series_row::{
SeriesRowPostDeleteInterceptor, SeriesRowPostInsertInterceptor, SeriesRowPostUpdateInterceptor,
SeriesRowPreDeleteInterceptor, SeriesRowPreInsertInterceptor, SeriesRowPreUpdateInterceptor,
},
table::{
TablePostCreateInterceptor, TablePostUpdateInterceptor, TablePreDeleteInterceptor,
TablePreUpdateInterceptor,
},
table_row::{
TableRowPostDeleteInterceptor, TableRowPostInsertInterceptor, TableRowPostUpdateInterceptor,
TableRowPreDeleteInterceptor, TableRowPreInsertInterceptor, TableRowPreUpdateInterceptor,
},
transaction::{PostCommitInterceptor, PreCommitContext, PreCommitInterceptor},
view::{
ViewPostCreateInterceptor, ViewPostUpdateInterceptor, ViewPreDeleteInterceptor,
ViewPreUpdateInterceptor,
},
},
multi::{RangeScope, transaction::write::WriteSavepoint},
single::{SingleTransaction, read::SingleReadTransaction, write::SingleWriteTransaction},
transaction::{admin::AdminTransaction, command::CommandTransaction, query::QueryTransaction, write::Write},
};
pub trait RqlExecutor: Send + Sync {
fn rql(&self, tx: &mut Transaction<'_>, rql: &str, params: Params) -> ExecutionResult;
}
pub mod admin;
pub mod catalog;
pub mod command;
pub mod query;
pub mod write;
use crate::multi::{pending::PendingWrites, transaction::write::MultiWriteTransaction};
#[inline]
pub(super) fn collect_transaction_writes(pending: &PendingWrites) -> Vec<(EncodedKey, Option<EncodedBytes>)> {
pending.iter()
.map(|(key, p)| match &p.delta {
Delta::Set {
bytes,
..
} => (key.encode(), Some(bytes.clone())),
_ => (key.encode(), None),
})
.collect()
}
#[inline]
pub(super) fn apply_pre_commit_writes(
multi: &mut MultiWriteTransaction,
pending_writes: &[(TaggedKey, PendingWrite)],
) -> Result<()> {
for (key, write) in pending_writes {
match write {
PendingWrite::Set(v) => multi.set(key, v.clone())?,
PendingWrite::Remove {
announce: RemoveVisibility::Announced,
} => multi.remove(key)?,
PendingWrite::Remove {
announce: RemoveVisibility::Unobserved,
} => multi.remove_unobserved(key)?,
PendingWrite::Remove {
announce: RemoveVisibility::Silent,
} => multi.remove_silent(key)?,
}
}
Ok(())
}
pub struct Savepoint {
write: WriteSavepoint,
row_changes_len: usize,
accumulator_len: usize,
changes: CatalogChangesSavepoint,
}
pub struct TestTransaction<'a> {
pub inner: &'a mut AdminTransaction,
pub baseline: usize,
pub events: &'a mut Vec<CapturedEvent>,
pub invocations: &'a mut Vec<CapturedInvocation>,
pub event_seq: &'a mut u64,
pub handler_seq: &'a mut u64,
pub savepoint: Option<Savepoint>,
pub session_type: SessionOp,
pub session_default_deny: bool,
}
impl<'a> TestTransaction<'a> {
pub fn new(
inner: &'a mut AdminTransaction,
events: &'a mut Vec<CapturedEvent>,
invocations: &'a mut Vec<CapturedInvocation>,
event_seq: &'a mut u64,
handler_seq: &'a mut u64,
session_type: SessionOp,
session_default_deny: bool,
) -> Self {
let baseline = inner.accumulator.len();
let savepoint = Savepoint {
write: inner.cmd.as_ref().unwrap().savepoint(),
row_changes_len: inner.row_changes.len(),
accumulator_len: inner.accumulator.len(),
changes: inner.changes.savepoint(),
};
Self {
inner,
baseline,
events,
invocations,
event_seq,
handler_seq,
savepoint: Some(savepoint),
session_type,
session_default_deny,
}
}
pub fn restore(&mut self) {
if let Some(sp) = self.savepoint.take() {
self.inner.cmd.as_mut().unwrap().restore_savepoint(sp.write);
self.inner.row_changes.truncate(sp.row_changes_len);
self.inner.accumulator.truncate(sp.accumulator_len);
self.inner.changes.restore_savepoint(sp.changes);
self.inner.unpoison();
}
}
pub fn reborrow(&mut self) -> TestTransaction<'_> {
TestTransaction {
inner: &mut *self.inner,
baseline: self.baseline,
events: &mut *self.events,
invocations: &mut *self.invocations,
event_seq: &mut *self.event_seq,
handler_seq: &mut *self.handler_seq,
savepoint: None,
session_type: self.session_type,
session_default_deny: self.session_default_deny,
}
}
pub fn accumulator_entries_from(&self) -> &[(ObjectId, Diff)] {
self.inner.accumulator.entries_from(self.baseline)
}
pub fn capture_testing_pre_commit(&mut self) -> Result<()> {
let has_source_changes = self
.inner
.accumulator
.entries_from(self.baseline)
.iter()
.any(|(id, _)| !matches!(id, ObjectId::View(_)));
if !has_source_changes {
return Ok(());
}
let offset = self.baseline;
let transaction_writes: Vec<(EncodedKey, Option<EncodedBytes>)> = self
.inner
.pending_writes()
.iter()
.map(|(key, pending)| match &pending.delta {
Delta::Set {
bytes,
..
} => (key.encode(), Some(bytes.clone())),
_ => (key.encode(), None),
})
.collect();
let (carried, flow_changes): (Vec<Change>, Vec<Change>) = self
.inner
.accumulator
.take_changes_from(offset, CommitVersion(0), self.inner.clock.now())?
.into_iter()
.partition(|change| matches!(change.origin, ChangeOrigin::Object(ObjectId::View(_))));
let mut ctx = PreCommitContext {
flow_changes,
pending_writes: Vec::new(),
transaction_writes,
view_entries: Vec::new(),
};
self.inner.interceptors.pre_commit.execute(&mut ctx)?;
for (key, write) in &ctx.pending_writes {
match write {
PendingWrite::Set(v) => self.inner.cmd.as_mut().unwrap().set(key, v.clone())?,
PendingWrite::Remove {
announce: RemoveVisibility::Announced,
} => self.inner.cmd.as_mut().unwrap().remove(key)?,
PendingWrite::Remove {
announce: RemoveVisibility::Unobserved,
} => self.inner.cmd.as_mut().unwrap().remove_unobserved(key)?,
PendingWrite::Remove {
announce: RemoveVisibility::Silent,
} => self.inner.cmd.as_mut().unwrap().remove_silent(key)?,
}
}
for change in carried {
if let ChangeOrigin::Object(id) = change.origin {
for diff in change.diffs {
self.inner.accumulator.track(id, diff);
}
}
}
for (id, diff) in ctx.view_entries {
self.inner.accumulator.track(id, diff);
}
Ok(())
}
}
pub enum Transaction<'a> {
Command(&'a mut CommandTransaction),
Admin(&'a mut AdminTransaction),
Query(&'a mut QueryTransaction),
Test(Box<TestTransaction<'a>>),
}
impl<'a> Transaction<'a> {
pub fn version(&self) -> CommitVersion {
match self {
Self::Command(txn) => txn.version(),
Self::Admin(txn) => txn.version(),
Self::Query(txn) => txn.version(),
Self::Test(t) => t.inner.version(),
}
}
pub fn id(&self) -> TransactionId {
match self {
Self::Command(txn) => txn.id(),
Self::Admin(txn) => txn.id(),
Self::Query(txn) => txn.id(),
Self::Test(t) => t.inner.id(),
}
}
pub fn has_unprocessed_flow_changes(&self) -> bool {
match self {
Self::Command(txn) => !txn.accumulator.is_empty(),
Self::Admin(txn) => !txn.accumulator.is_empty(),
Self::Query(_) | Self::Test(_) => false,
}
}
pub fn unprocessed_flow_change_objects(&self) -> Vec<ObjectId> {
match self {
Self::Command(txn) => txn.accumulator.pending_objects(),
Self::Admin(txn) => txn.accumulator.pending_objects(),
Self::Query(_) | Self::Test(_) => Vec::new(),
}
}
pub fn get<K: Into<TaggedKey> + Clone>(&mut self, key: &K) -> Result<Option<MultiVersionRow<TaggedKey>>> {
match self {
Self::Command(txn) => txn.get(key),
Self::Admin(txn) => txn.get(key),
Self::Query(txn) => txn.get(key),
Self::Test(t) => t.inner.get(key),
}
}
pub fn get_committed<K: Into<TaggedKey> + Clone>(
&mut self,
key: &K,
) -> Result<Option<MultiVersionRow<TaggedKey>>> {
match self {
Self::Command(txn) => txn.get_committed(key),
Self::Admin(txn) => txn.get_committed(key),
Self::Query(txn) => txn.get(key),
Self::Test(t) => t.inner.get_committed(key),
}
}
pub fn contains<K: Into<TaggedKey> + Clone>(&mut self, key: &K) -> Result<bool> {
match self {
Self::Command(txn) => txn.contains(key),
Self::Admin(txn) => txn.contains(key),
Self::Query(txn) => txn.contains(key),
Self::Test(t) => t.inner.contains(key),
}
}
pub fn prefix(&mut self, prefix: &EncodedKey) -> Result<MultiVersionBatch<TaggedKey>> {
match self {
Self::Command(txn) => txn.prefix(prefix),
Self::Admin(txn) => txn.prefix(prefix),
Self::Query(txn) => txn.prefix(prefix),
Self::Test(t) => t.inner.prefix(prefix),
}
}
pub fn prefix_rev(&mut self, prefix: &EncodedKey) -> Result<MultiVersionBatch<TaggedKey>> {
match self {
Self::Command(txn) => txn.prefix_rev(prefix),
Self::Admin(txn) => txn.prefix_rev(prefix),
Self::Query(txn) => txn.prefix_rev(prefix),
Self::Test(t) => t.inner.prefix_rev(prefix),
}
}
pub fn read_as_of_version_exclusive(&mut self, version: CommitVersion) -> Result<()> {
match self {
Transaction::Command(txn) => txn.read_as_of_version_exclusive(version),
Transaction::Admin(txn) => txn.read_as_of_version_exclusive(version),
Transaction::Query(txn) => txn.read_as_of_version_exclusive(version),
Transaction::Test(t) => t.inner.read_as_of_version_exclusive(version),
}
}
pub fn range(
&mut self,
range: TaggedKeyBoundRange,
scope: RangeScope,
batch_size: usize,
) -> Result<Box<dyn Iterator<Item = Result<MultiVersionRow<TaggedKey>>> + Send + '_>> {
match self {
Transaction::Command(txn) => txn.range(range, scope, batch_size),
Transaction::Admin(txn) => txn.range(range, scope, batch_size),
Transaction::Query(txn) => Ok(txn.range(range, scope, batch_size)),
Transaction::Test(t) => t.inner.range(range, scope, batch_size),
}
}
pub fn range_row(
&mut self,
storage: StorageId,
start: Bound<StorageRowKey>,
end: Bound<StorageRowKey>,
scope: RangeScope,
batch_size: usize,
) -> Result<Box<dyn Iterator<Item = Result<MultiVersionRow<StorageRowKey>>> + Send + '_>> {
match self {
Transaction::Command(txn) => txn.range_row(storage, start, end, scope, batch_size),
Transaction::Admin(txn) => txn.range_row(storage, start, end, scope, batch_size),
Transaction::Query(txn) => Ok(txn.range_row(storage, start, end, scope, batch_size)),
Transaction::Test(t) => t.inner.range_row(storage, start, end, scope, batch_size),
}
}
#[inline]
pub fn range_partitioned_row(
&mut self,
storage: StorageId,
start: Bound<StoragePartitionedRowKey>,
end: Bound<StoragePartitionedRowKey>,
scope: RangeScope,
batch_size: usize,
) -> Result<Box<dyn Iterator<Item = Result<MultiVersionRow<StoragePartitionedRowKey>>> + Send + '_>> {
match self {
Transaction::Command(txn) => txn.range_partitioned_row(storage, start, end, scope, batch_size),
Transaction::Admin(txn) => txn.range_partitioned_row(storage, start, end, scope, batch_size),
Transaction::Query(txn) => {
Ok(txn.range_partitioned_row(storage, start, end, scope, batch_size))
}
Transaction::Test(t) => t.inner.range_partitioned_row(storage, start, end, scope, batch_size),
}
}
pub fn range_rev(
&mut self,
range: TaggedKeyBoundRange,
scope: RangeScope,
batch_size: usize,
) -> Result<Box<dyn Iterator<Item = Result<MultiVersionRow<TaggedKey>>> + Send + '_>> {
match self {
Transaction::Command(txn) => txn.range_rev(range, scope, batch_size),
Transaction::Admin(txn) => txn.range_rev(range, scope, batch_size),
Transaction::Query(txn) => Ok(txn.range_rev(range, scope, batch_size)),
Transaction::Test(t) => t.inner.range_rev(range, scope, batch_size),
}
}
}
impl<'a> From<&'a mut CommandTransaction> for Transaction<'a> {
fn from(txn: &'a mut CommandTransaction) -> Self {
Self::Command(txn)
}
}
impl<'a> From<&'a mut AdminTransaction> for Transaction<'a> {
fn from(txn: &'a mut AdminTransaction) -> Self {
Self::Admin(txn)
}
}
impl<'a> From<&'a mut QueryTransaction> for Transaction<'a> {
fn from(txn: &'a mut QueryTransaction) -> Self {
Self::Query(txn)
}
}
impl<'a> Transaction<'a> {
pub fn identity(&self) -> IdentityId {
match self {
Self::Command(txn) => txn.identity,
Self::Admin(txn) => txn.identity,
Self::Query(txn) => txn.identity,
Self::Test(t) => t.inner.identity,
}
}
pub fn set_identity(&mut self, identity: IdentityId) {
match self {
Self::Command(txn) => txn.identity = identity,
Self::Admin(txn) => txn.identity = identity,
Self::Query(txn) => txn.identity = identity,
Self::Test(t) => t.inner.identity = identity,
}
}
fn executor_clone(&self) -> Option<Arc<dyn RqlExecutor>> {
match self {
Self::Command(txn) => txn.executor.clone(),
Self::Admin(txn) => txn.executor.clone(),
Self::Query(txn) => txn.executor.clone(),
Self::Test(t) => t.inner.executor.clone(),
}
}
pub fn rql(&mut self, rql: &str, params: Params) -> ExecutionResult {
let executor = self.executor_clone().expect("RqlExecutor not set");
let mut tx = self.reborrow();
let result = executor.rql(&mut tx, rql, params);
if let Some(ref e) = result.error {
self.poison(*e.0.clone());
}
result
}
fn poison(&mut self, cause: Diagnostic) {
match self {
Transaction::Command(txn) => txn.poison(cause),
Transaction::Admin(txn) => txn.poison(cause),
Transaction::Query(_) => {}
Transaction::Test(t) => t.inner.poison(cause),
}
}
pub fn reborrow(&mut self) -> Transaction<'_> {
match self {
Transaction::Command(cmd) => Transaction::Command(cmd),
Transaction::Admin(admin) => Transaction::Admin(admin),
Transaction::Query(qry) => Transaction::Query(qry),
Transaction::Test(t) => Transaction::Test(Box::new(TestTransaction {
inner: t.inner,
baseline: t.baseline,
events: t.events,
invocations: t.invocations,
event_seq: t.event_seq,
handler_seq: t.handler_seq,
savepoint: None,
session_type: t.session_type,
session_default_deny: t.session_default_deny,
})),
}
}
pub fn command(self) -> &'a mut CommandTransaction {
match self {
Self::Command(txn) => txn,
_ => panic!("Expected Command transaction"),
}
}
pub fn admin(self) -> &'a mut AdminTransaction {
match self {
Self::Admin(txn) => txn,
Self::Test(t) => t.inner,
_ => panic!("Expected Admin transaction"),
}
}
pub fn query(self) -> &'a mut QueryTransaction {
match self {
Self::Query(txn) => txn,
_ => panic!("Expected Query transaction"),
}
}
pub fn admin_mut(&mut self) -> &mut AdminTransaction {
match self {
Self::Admin(txn) => txn,
Self::Test(t) => t.inner,
_ => panic!("Expected Admin transaction"),
}
}
pub fn begin_single_query<'b, I>(&self, keys: I) -> Result<SingleReadTransaction<'_>>
where
I: IntoIterator<Item = &'b EncodedKey>,
{
match self {
Transaction::Command(txn) => txn.begin_single_query(keys),
Transaction::Admin(txn) => txn.begin_single_query(keys),
Transaction::Query(txn) => txn.begin_single_query(keys),
Transaction::Test(t) => t.inner.begin_single_query(keys),
}
}
pub fn begin_single_command<'b, I>(&self, keys: I) -> Result<SingleWriteTransaction<'_>>
where
I: IntoIterator<Item = &'b EncodedKey>,
{
match self {
Transaction::Command(txn) => txn.begin_single_command(keys),
Transaction::Admin(txn) => txn.begin_single_command(keys),
Transaction::Query(_) => panic!("Write operations not supported on Query transaction"),
Transaction::Test(t) => t.inner.begin_single_command(keys),
}
}
pub fn single(&self) -> Option<&SingleTransaction> {
match self {
Transaction::Command(txn) => Some(&txn.single),
Transaction::Admin(txn) => Some(&txn.single),
Transaction::Query(txn) => txn.single.as_ref(),
Transaction::Test(t) => Some(&t.inner.single),
}
}
fn write_ops(&mut self) -> &mut dyn Write {
match self {
Transaction::Command(txn) => &mut **txn,
Transaction::Admin(txn) => &mut **txn,
Transaction::Query(_) => panic!("Write operations not supported on Query transaction"),
Transaction::Test(t) => &mut *t.inner,
}
}
pub fn set<K: Into<TaggedKey> + Clone>(&mut self, key: &K, bytes: impl Into<EncodedBytes>) -> Result<()> {
Write::set(self.write_ops(), &key.clone().into(), bytes.into())
}
pub fn remove_with_pre<K: Into<TaggedKey> + Clone>(&mut self, key: &K, pre: EncodedBytes) -> Result<()> {
Write::remove_with_pre(self.write_ops(), &key.clone().into(), pre)
}
pub fn remove<K: Into<TaggedKey> + Clone>(&mut self, key: &K) -> Result<()> {
Write::remove(self.write_ops(), &key.clone().into())
}
pub fn mark_preexisting<K: Into<TaggedKey> + Clone>(&mut self, key: &K) -> Result<()> {
Write::mark_preexisting(self.write_ops(), &key.clone().into())
}
pub fn track_row_change(&mut self, changes: &[RowChange]) {
Write::track_row_change(self.write_ops(), changes)
}
pub fn track_flow_change(&mut self, change: Change) {
Write::track_flow_change(self.write_ops(), change)
}
pub fn record_test_event(
&mut self,
namespace: String,
event: String,
variant: String,
depth: u8,
columns: Columns,
) {
if let Transaction::Test(t) = self {
*t.event_seq += 1;
t.events.push(CapturedEvent {
sequence: *t.event_seq,
namespace,
event,
variant,
depth,
columns,
});
}
}
pub fn record_test_handler(&mut self, mut invocation: CapturedInvocation) {
if let Transaction::Test(t) = self {
*t.handler_seq += 1;
invocation.sequence = *t.handler_seq;
t.invocations.push(invocation);
}
}
}
macro_rules! delegate_interceptor {
($method:ident, $ret:ty) => {
fn $method(&mut self) -> $ret {
match self {
Transaction::Command(txn) => txn.$method(),
Transaction::Admin(txn) => txn.$method(),
Transaction::Query(_) => panic!("Interceptors not supported on Query transaction"),
Transaction::Test(t) => t.inner.$method(),
}
}
};
}
impl WithInterceptors for Transaction<'_> {
delegate_interceptor!(
table_row_pre_insert_interceptors,
&mut Chain<dyn TableRowPreInsertInterceptor + Send + Sync>
);
delegate_interceptor!(
table_row_post_insert_interceptors,
&mut Chain<dyn TableRowPostInsertInterceptor + Send + Sync>
);
delegate_interceptor!(
table_row_pre_update_interceptors,
&mut Chain<dyn TableRowPreUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
table_row_post_update_interceptors,
&mut Chain<dyn TableRowPostUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
table_row_pre_delete_interceptors,
&mut Chain<dyn TableRowPreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
table_row_post_delete_interceptors,
&mut Chain<dyn TableRowPostDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_row_pre_insert_interceptors,
&mut Chain<dyn RingBufferRowPreInsertInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_row_post_insert_interceptors,
&mut Chain<dyn RingBufferRowPostInsertInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_row_pre_update_interceptors,
&mut Chain<dyn RingBufferRowPreUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_row_post_update_interceptors,
&mut Chain<dyn RingBufferRowPostUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_row_pre_delete_interceptors,
&mut Chain<dyn RingBufferRowPreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_row_post_delete_interceptors,
&mut Chain<dyn RingBufferRowPostDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(pre_commit_interceptors, &mut Chain<dyn PreCommitInterceptor + Send + Sync>);
delegate_interceptor!(post_commit_interceptors, &mut Chain<dyn PostCommitInterceptor + Send + Sync>);
delegate_interceptor!(
namespace_post_create_interceptors,
&mut Chain<dyn NamespacePostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(
namespace_pre_update_interceptors,
&mut Chain<dyn NamespacePreUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
namespace_post_update_interceptors,
&mut Chain<dyn NamespacePostUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
namespace_pre_delete_interceptors,
&mut Chain<dyn NamespacePreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(table_post_create_interceptors, &mut Chain<dyn TablePostCreateInterceptor + Send + Sync>);
delegate_interceptor!(table_pre_update_interceptors, &mut Chain<dyn TablePreUpdateInterceptor + Send + Sync>);
delegate_interceptor!(table_post_update_interceptors, &mut Chain<dyn TablePostUpdateInterceptor + Send + Sync>);
delegate_interceptor!(table_pre_delete_interceptors, &mut Chain<dyn TablePreDeleteInterceptor + Send + Sync>);
delegate_interceptor!(view_post_create_interceptors, &mut Chain<dyn ViewPostCreateInterceptor + Send + Sync>);
delegate_interceptor!(view_pre_update_interceptors, &mut Chain<dyn ViewPreUpdateInterceptor + Send + Sync>);
delegate_interceptor!(view_post_update_interceptors, &mut Chain<dyn ViewPostUpdateInterceptor + Send + Sync>);
delegate_interceptor!(view_pre_delete_interceptors, &mut Chain<dyn ViewPreDeleteInterceptor + Send + Sync>);
delegate_interceptor!(
ringbuffer_post_create_interceptors,
&mut Chain<dyn RingBufferPostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_pre_update_interceptors,
&mut Chain<dyn RingBufferPreUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_post_update_interceptors,
&mut Chain<dyn RingBufferPostUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
ringbuffer_pre_delete_interceptors,
&mut Chain<dyn RingBufferPreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_row_pre_insert_interceptors,
&mut Chain<dyn DictionaryRowPreInsertInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_row_post_insert_interceptors,
&mut Chain<dyn DictionaryRowPostInsertInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_row_pre_update_interceptors,
&mut Chain<dyn DictionaryRowPreUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_row_post_update_interceptors,
&mut Chain<dyn DictionaryRowPostUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_row_pre_delete_interceptors,
&mut Chain<dyn DictionaryRowPreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_row_post_delete_interceptors,
&mut Chain<dyn DictionaryRowPostDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_post_create_interceptors,
&mut Chain<dyn DictionaryPostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_pre_update_interceptors,
&mut Chain<dyn DictionaryPreUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_post_update_interceptors,
&mut Chain<dyn DictionaryPostUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
dictionary_pre_delete_interceptors,
&mut Chain<dyn DictionaryPreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
series_row_pre_insert_interceptors,
&mut Chain<dyn SeriesRowPreInsertInterceptor + Send + Sync>
);
delegate_interceptor!(
series_row_post_insert_interceptors,
&mut Chain<dyn SeriesRowPostInsertInterceptor + Send + Sync>
);
delegate_interceptor!(
series_row_pre_update_interceptors,
&mut Chain<dyn SeriesRowPreUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
series_row_post_update_interceptors,
&mut Chain<dyn SeriesRowPostUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(
series_row_pre_delete_interceptors,
&mut Chain<dyn SeriesRowPreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
series_row_post_delete_interceptors,
&mut Chain<dyn SeriesRowPostDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
series_post_create_interceptors,
&mut Chain<dyn SeriesPostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(series_pre_update_interceptors, &mut Chain<dyn SeriesPreUpdateInterceptor + Send + Sync>);
delegate_interceptor!(
series_post_update_interceptors,
&mut Chain<dyn SeriesPostUpdateInterceptor + Send + Sync>
);
delegate_interceptor!(series_pre_delete_interceptors, &mut Chain<dyn SeriesPreDeleteInterceptor + Send + Sync>);
delegate_interceptor!(
identity_post_create_interceptors,
&mut Chain<dyn IdentityPostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(
identity_pre_delete_interceptors,
&mut Chain<dyn IdentityPreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(role_post_create_interceptors, &mut Chain<dyn RolePostCreateInterceptor + Send + Sync>);
delegate_interceptor!(role_pre_delete_interceptors, &mut Chain<dyn RolePreDeleteInterceptor + Send + Sync>);
delegate_interceptor!(
granted_role_post_create_interceptors,
&mut Chain<dyn GrantedRolePostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(
granted_role_pre_delete_interceptors,
&mut Chain<dyn GrantedRolePreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
identity_attribute_post_create_interceptors,
&mut Chain<dyn IdentityAttributePostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(
identity_attribute_pre_delete_interceptors,
&mut Chain<dyn IdentityAttributePreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
identity_attribute_value_post_create_interceptors,
&mut Chain<dyn IdentityAttributeValuePostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(
identity_attribute_value_pre_delete_interceptors,
&mut Chain<dyn IdentityAttributeValuePreDeleteInterceptor + Send + Sync>
);
delegate_interceptor!(
authentication_post_create_interceptors,
&mut Chain<dyn AuthenticationPostCreateInterceptor + Send + Sync>
);
delegate_interceptor!(
authentication_pre_delete_interceptors,
&mut Chain<dyn AuthenticationPreDeleteInterceptor + Send + Sync>
);
}