Skip to main content

reifydb_transaction/interceptor/
view_row.rs

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