Skip to main content

reifydb_transaction/interceptor/
view.rs

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