Skip to main content

reifydb_transaction/interceptor/
table.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_core::{encoded::encoded::EncodedValues, interface::catalog::table::TableDef};
5use reifydb_type::{Result, value::row_number::RowNumber};
6
7use super::WithInterceptors;
8use crate::interceptor::chain::InterceptorChain;
9
10// PRE INSERT
11/// Context for table pre-insert interceptors
12pub struct TablePreInsertContext<'a> {
13	pub table: &'a TableDef,
14	pub rn: RowNumber,
15	pub row: &'a EncodedValues,
16}
17
18impl<'a> TablePreInsertContext<'a> {
19	pub fn new(table: &'a TableDef, rn: RowNumber, row: &'a EncodedValues) -> Self {
20		Self {
21			table,
22			rn,
23			row,
24		}
25	}
26}
27
28pub trait TablePreInsertInterceptor: Send + Sync {
29	fn intercept<'a>(&self, ctx: &mut TablePreInsertContext<'a>) -> Result<()>;
30}
31
32impl InterceptorChain<dyn TablePreInsertInterceptor + Send + Sync> {
33	pub fn execute(&self, mut ctx: TablePreInsertContext) -> Result<()> {
34		for interceptor in &self.interceptors {
35			interceptor.intercept(&mut ctx)?;
36		}
37		Ok(())
38	}
39}
40
41pub struct ClosureTablePreInsertInterceptor<F>
42where
43	F: for<'a> Fn(&mut TablePreInsertContext<'a>) -> Result<()> + Send + Sync,
44{
45	closure: F,
46}
47
48impl<F> ClosureTablePreInsertInterceptor<F>
49where
50	F: for<'a> Fn(&mut TablePreInsertContext<'a>) -> Result<()> + Send + Sync,
51{
52	pub fn new(closure: F) -> Self {
53		Self {
54			closure,
55		}
56	}
57}
58
59impl<F> Clone for ClosureTablePreInsertInterceptor<F>
60where
61	F: for<'a> Fn(&mut TablePreInsertContext<'a>) -> Result<()> + Send + Sync + Clone,
62{
63	fn clone(&self) -> Self {
64		Self {
65			closure: self.closure.clone(),
66		}
67	}
68}
69
70impl<F> TablePreInsertInterceptor for ClosureTablePreInsertInterceptor<F>
71where
72	F: for<'a> Fn(&mut TablePreInsertContext<'a>) -> Result<()> + Send + Sync,
73{
74	fn intercept<'a>(&self, ctx: &mut TablePreInsertContext<'a>) -> Result<()> {
75		(self.closure)(ctx)
76	}
77}
78
79pub fn table_pre_insert<F>(f: F) -> ClosureTablePreInsertInterceptor<F>
80where
81	F: for<'a> Fn(&mut TablePreInsertContext<'a>) -> Result<()> + Send + Sync + Clone + 'static,
82{
83	ClosureTablePreInsertInterceptor::new(f)
84}
85
86// POST INSERT
87/// Context for table post-insert interceptors
88pub struct TablePostInsertContext<'a> {
89	pub table: &'a TableDef,
90	pub id: RowNumber,
91	pub row: &'a EncodedValues,
92}
93
94impl<'a> TablePostInsertContext<'a> {
95	pub fn new(table: &'a TableDef, id: RowNumber, row: &'a EncodedValues) -> Self {
96		Self {
97			table,
98			id,
99			row,
100		}
101	}
102}
103
104pub trait TablePostInsertInterceptor: Send + Sync {
105	fn intercept<'a>(&self, ctx: &mut TablePostInsertContext<'a>) -> Result<()>;
106}
107
108impl InterceptorChain<dyn TablePostInsertInterceptor + Send + Sync> {
109	pub fn execute(&self, mut ctx: TablePostInsertContext) -> Result<()> {
110		for interceptor in &self.interceptors {
111			interceptor.intercept(&mut ctx)?;
112		}
113		Ok(())
114	}
115}
116
117pub struct ClosureTablePostInsertInterceptor<F>
118where
119	F: for<'a> Fn(&mut TablePostInsertContext<'a>) -> Result<()> + Send + Sync,
120{
121	closure: F,
122}
123
124impl<F> ClosureTablePostInsertInterceptor<F>
125where
126	F: for<'a> Fn(&mut TablePostInsertContext<'a>) -> Result<()> + Send + Sync,
127{
128	pub fn new(closure: F) -> Self {
129		Self {
130			closure,
131		}
132	}
133}
134
135impl<F> Clone for ClosureTablePostInsertInterceptor<F>
136where
137	F: for<'a> Fn(&mut TablePostInsertContext<'a>) -> Result<()> + Send + Sync + Clone,
138{
139	fn clone(&self) -> Self {
140		Self {
141			closure: self.closure.clone(),
142		}
143	}
144}
145
146impl<F> TablePostInsertInterceptor for ClosureTablePostInsertInterceptor<F>
147where
148	F: for<'a> Fn(&mut TablePostInsertContext<'a>) -> Result<()> + Send + Sync,
149{
150	fn intercept<'a>(&self, ctx: &mut TablePostInsertContext<'a>) -> Result<()> {
151		(self.closure)(ctx)
152	}
153}
154
155pub fn table_post_insert<F>(f: F) -> ClosureTablePostInsertInterceptor<F>
156where
157	F: for<'a> Fn(&mut TablePostInsertContext<'a>) -> Result<()> + Send + Sync + Clone + 'static,
158{
159	ClosureTablePostInsertInterceptor::new(f)
160}
161
162// PRE UPDATE
163/// Context for table pre-update interceptors
164pub struct TablePreUpdateContext<'a> {
165	pub table: &'a TableDef,
166	pub id: RowNumber,
167	pub row: &'a EncodedValues,
168}
169
170impl<'a> TablePreUpdateContext<'a> {
171	pub fn new(table: &'a TableDef, id: RowNumber, row: &'a EncodedValues) -> Self {
172		Self {
173			table,
174			id,
175			row,
176		}
177	}
178}
179
180pub trait TablePreUpdateInterceptor: Send + Sync {
181	fn intercept<'a>(&self, ctx: &mut TablePreUpdateContext<'a>) -> Result<()>;
182}
183
184impl InterceptorChain<dyn TablePreUpdateInterceptor + Send + Sync> {
185	pub fn execute(&self, mut ctx: TablePreUpdateContext) -> Result<()> {
186		for interceptor in &self.interceptors {
187			interceptor.intercept(&mut ctx)?;
188		}
189		Ok(())
190	}
191}
192
193pub struct ClosureTablePreUpdateInterceptor<F>
194where
195	F: for<'a> Fn(&mut TablePreUpdateContext<'a>) -> Result<()> + Send + Sync,
196{
197	closure: F,
198}
199
200impl<F> ClosureTablePreUpdateInterceptor<F>
201where
202	F: for<'a> Fn(&mut TablePreUpdateContext<'a>) -> Result<()> + Send + Sync,
203{
204	pub fn new(closure: F) -> Self {
205		Self {
206			closure,
207		}
208	}
209}
210
211impl<F> Clone for ClosureTablePreUpdateInterceptor<F>
212where
213	F: for<'a> Fn(&mut TablePreUpdateContext<'a>) -> Result<()> + Send + Sync + Clone,
214{
215	fn clone(&self) -> Self {
216		Self {
217			closure: self.closure.clone(),
218		}
219	}
220}
221
222impl<F> TablePreUpdateInterceptor for ClosureTablePreUpdateInterceptor<F>
223where
224	F: for<'a> Fn(&mut TablePreUpdateContext<'a>) -> Result<()> + Send + Sync,
225{
226	fn intercept<'a>(&self, ctx: &mut TablePreUpdateContext<'a>) -> Result<()> {
227		(self.closure)(ctx)
228	}
229}
230
231pub fn table_pre_update<F>(f: F) -> ClosureTablePreUpdateInterceptor<F>
232where
233	F: for<'a> Fn(&mut TablePreUpdateContext<'a>) -> Result<()> + Send + Sync + Clone + 'static,
234{
235	ClosureTablePreUpdateInterceptor::new(f)
236}
237
238// POST UPDATE
239/// Context for table post-update interceptors
240pub struct TablePostUpdateContext<'a> {
241	pub table: &'a TableDef,
242	pub id: RowNumber,
243	pub row: &'a EncodedValues,
244	pub old_row: &'a EncodedValues,
245}
246
247impl<'a> TablePostUpdateContext<'a> {
248	pub fn new(table: &'a TableDef, id: RowNumber, row: &'a EncodedValues, old_row: &'a EncodedValues) -> Self {
249		Self {
250			table,
251			id,
252			row,
253			old_row,
254		}
255	}
256}
257
258pub trait TablePostUpdateInterceptor: Send + Sync {
259	fn intercept<'a>(&self, ctx: &mut TablePostUpdateContext<'a>) -> Result<()>;
260}
261
262impl InterceptorChain<dyn TablePostUpdateInterceptor + Send + Sync> {
263	pub fn execute(&self, mut ctx: TablePostUpdateContext) -> Result<()> {
264		for interceptor in &self.interceptors {
265			interceptor.intercept(&mut ctx)?;
266		}
267		Ok(())
268	}
269}
270
271pub struct ClosureTablePostUpdateInterceptor<F>
272where
273	F: for<'a> Fn(&mut TablePostUpdateContext<'a>) -> Result<()> + Send + Sync,
274{
275	closure: F,
276}
277
278impl<F> ClosureTablePostUpdateInterceptor<F>
279where
280	F: for<'a> Fn(&mut TablePostUpdateContext<'a>) -> Result<()> + Send + Sync,
281{
282	pub fn new(closure: F) -> Self {
283		Self {
284			closure,
285		}
286	}
287}
288
289impl<F> Clone for ClosureTablePostUpdateInterceptor<F>
290where
291	F: for<'a> Fn(&mut TablePostUpdateContext<'a>) -> Result<()> + Send + Sync + Clone,
292{
293	fn clone(&self) -> Self {
294		Self {
295			closure: self.closure.clone(),
296		}
297	}
298}
299
300impl<F> TablePostUpdateInterceptor for ClosureTablePostUpdateInterceptor<F>
301where
302	F: for<'a> Fn(&mut TablePostUpdateContext<'a>) -> Result<()> + Send + Sync,
303{
304	fn intercept<'a>(&self, ctx: &mut TablePostUpdateContext<'a>) -> Result<()> {
305		(self.closure)(ctx)
306	}
307}
308
309pub fn table_post_update<F>(f: F) -> ClosureTablePostUpdateInterceptor<F>
310where
311	F: for<'a> Fn(&mut TablePostUpdateContext<'a>) -> Result<()> + Send + Sync + Clone + 'static,
312{
313	ClosureTablePostUpdateInterceptor::new(f)
314}
315
316// PRE DELETE
317/// Context for table pre-delete interceptors
318pub struct TablePreDeleteContext<'a> {
319	pub table: &'a TableDef,
320	pub id: RowNumber,
321}
322
323impl<'a> TablePreDeleteContext<'a> {
324	pub fn new(table: &'a TableDef, id: RowNumber) -> Self {
325		Self {
326			table,
327			id,
328		}
329	}
330}
331
332pub trait TablePreDeleteInterceptor: Send + Sync {
333	fn intercept<'a>(&self, ctx: &mut TablePreDeleteContext<'a>) -> Result<()>;
334}
335
336impl InterceptorChain<dyn TablePreDeleteInterceptor + Send + Sync> {
337	pub fn execute(&self, mut ctx: TablePreDeleteContext) -> Result<()> {
338		for interceptor in &self.interceptors {
339			interceptor.intercept(&mut ctx)?;
340		}
341		Ok(())
342	}
343}
344
345pub struct ClosureTablePreDeleteInterceptor<F>
346where
347	F: for<'a> Fn(&mut TablePreDeleteContext<'a>) -> Result<()> + Send + Sync,
348{
349	closure: F,
350}
351
352impl<F> ClosureTablePreDeleteInterceptor<F>
353where
354	F: for<'a> Fn(&mut TablePreDeleteContext<'a>) -> Result<()> + Send + Sync,
355{
356	pub fn new(closure: F) -> Self {
357		Self {
358			closure,
359		}
360	}
361}
362
363impl<F> Clone for ClosureTablePreDeleteInterceptor<F>
364where
365	F: for<'a> Fn(&mut TablePreDeleteContext<'a>) -> Result<()> + Send + Sync + Clone,
366{
367	fn clone(&self) -> Self {
368		Self {
369			closure: self.closure.clone(),
370		}
371	}
372}
373
374impl<F> TablePreDeleteInterceptor for ClosureTablePreDeleteInterceptor<F>
375where
376	F: for<'a> Fn(&mut TablePreDeleteContext<'a>) -> Result<()> + Send + Sync,
377{
378	fn intercept<'a>(&self, ctx: &mut TablePreDeleteContext<'a>) -> Result<()> {
379		(self.closure)(ctx)
380	}
381}
382
383pub fn table_pre_delete<F>(f: F) -> ClosureTablePreDeleteInterceptor<F>
384where
385	F: for<'a> Fn(&mut TablePreDeleteContext<'a>) -> Result<()> + Send + Sync + Clone + 'static,
386{
387	ClosureTablePreDeleteInterceptor::new(f)
388}
389
390// POST DELETE
391/// Context for table post-delete interceptors
392pub struct TablePostDeleteContext<'a> {
393	pub table: &'a TableDef,
394	pub id: RowNumber,
395	pub deleted_row: &'a EncodedValues,
396}
397
398impl<'a> TablePostDeleteContext<'a> {
399	pub fn new(table: &'a TableDef, id: RowNumber, deleted_row: &'a EncodedValues) -> Self {
400		Self {
401			table,
402			id,
403			deleted_row,
404		}
405	}
406}
407
408pub trait TablePostDeleteInterceptor: Send + Sync {
409	fn intercept<'a>(&self, ctx: &mut TablePostDeleteContext<'a>) -> Result<()>;
410}
411
412impl InterceptorChain<dyn TablePostDeleteInterceptor + Send + Sync> {
413	pub fn execute(&self, mut ctx: TablePostDeleteContext) -> Result<()> {
414		for interceptor in &self.interceptors {
415			interceptor.intercept(&mut ctx)?;
416		}
417		Ok(())
418	}
419}
420
421pub struct ClosureTablePostDeleteInterceptor<F>
422where
423	F: for<'a> Fn(&mut TablePostDeleteContext<'a>) -> Result<()> + Send + Sync,
424{
425	closure: F,
426}
427
428impl<F> ClosureTablePostDeleteInterceptor<F>
429where
430	F: for<'a> Fn(&mut TablePostDeleteContext<'a>) -> Result<()> + Send + Sync,
431{
432	pub fn new(closure: F) -> Self {
433		Self {
434			closure,
435		}
436	}
437}
438
439impl<F> Clone for ClosureTablePostDeleteInterceptor<F>
440where
441	F: for<'a> Fn(&mut TablePostDeleteContext<'a>) -> Result<()> + Send + Sync + Clone,
442{
443	fn clone(&self) -> Self {
444		Self {
445			closure: self.closure.clone(),
446		}
447	}
448}
449
450impl<F> TablePostDeleteInterceptor for ClosureTablePostDeleteInterceptor<F>
451where
452	F: for<'a> Fn(&mut TablePostDeleteContext<'a>) -> Result<()> + Send + Sync,
453{
454	fn intercept<'a>(&self, ctx: &mut TablePostDeleteContext<'a>) -> Result<()> {
455		(self.closure)(ctx)
456	}
457}
458
459pub fn table_post_delete<F>(f: F) -> ClosureTablePostDeleteInterceptor<F>
460where
461	F: for<'a> Fn(&mut TablePostDeleteContext<'a>) -> Result<()> + Send + Sync + Clone + 'static,
462{
463	ClosureTablePostDeleteInterceptor::new(f)
464}
465
466/// Helper struct for executing table interceptors via static methods.
467pub struct TableInterceptor;
468
469impl TableInterceptor {
470	pub fn pre_insert(
471		txn: &mut impl WithInterceptors,
472		table: &TableDef,
473		rn: RowNumber,
474		row: &EncodedValues,
475	) -> Result<()> {
476		let ctx = TablePreInsertContext::new(table, rn, row);
477		txn.table_pre_insert_interceptors().execute(ctx)
478	}
479
480	pub fn post_insert(
481		txn: &mut impl WithInterceptors,
482		table: &TableDef,
483		id: RowNumber,
484		row: &EncodedValues,
485	) -> Result<()> {
486		let ctx = TablePostInsertContext::new(table, id, row);
487		txn.table_post_insert_interceptors().execute(ctx)
488	}
489
490	pub fn pre_update(
491		txn: &mut impl WithInterceptors,
492		table: &TableDef,
493		id: RowNumber,
494		row: &EncodedValues,
495	) -> Result<()> {
496		let ctx = TablePreUpdateContext::new(table, id, row);
497		txn.table_pre_update_interceptors().execute(ctx)
498	}
499
500	pub fn post_update(
501		txn: &mut impl WithInterceptors,
502		table: &TableDef,
503		id: RowNumber,
504		row: &EncodedValues,
505		old_row: &EncodedValues,
506	) -> Result<()> {
507		let ctx = TablePostUpdateContext::new(table, id, row, old_row);
508		txn.table_post_update_interceptors().execute(ctx)
509	}
510
511	pub fn pre_delete(txn: &mut impl WithInterceptors, table: &TableDef, id: RowNumber) -> Result<()> {
512		let ctx = TablePreDeleteContext::new(table, id);
513		txn.table_pre_delete_interceptors().execute(ctx)
514	}
515
516	pub fn post_delete(
517		txn: &mut impl WithInterceptors,
518		table: &TableDef,
519		id: RowNumber,
520		deleted_row: &EncodedValues,
521	) -> Result<()> {
522		let ctx = TablePostDeleteContext::new(table, id, deleted_row);
523		txn.table_post_delete_interceptors().execute(ctx)
524	}
525}