Skip to main content

reifydb_transaction/interceptor/
dictionary_row.rs

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