Skip to main content

reifydb_transaction/interceptor/
table_row.rs

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