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