Skip to main content

feldera_sqllib/
lib.rs

1#![allow(non_snake_case)]
2
3#[doc(hidden)]
4pub mod aggregates;
5pub use aggregates::*;
6pub mod array;
7pub use array::*;
8#[doc(hidden)]
9pub mod binary;
10pub use binary::*;
11#[doc(hidden)]
12pub mod casts;
13pub use casts::*;
14#[doc(hidden)]
15pub mod decimal;
16pub use decimal::*;
17#[doc(hidden)]
18pub mod error;
19pub use error::*;
20#[doc(hidden)]
21pub mod float;
22pub use float::*;
23#[doc(hidden)]
24pub mod geopoint;
25pub use geopoint::*;
26#[doc(hidden)]
27pub mod interval;
28pub use interval::*;
29#[doc(hidden)]
30pub mod map;
31pub use map::*;
32#[doc(hidden)]
33pub mod operators;
34pub use operators::*;
35#[doc(hidden)]
36pub mod source;
37pub use source::*;
38#[doc(hidden)]
39pub mod string;
40pub use string::*;
41#[doc(hidden)]
42pub mod timestamp;
43pub use timestamp::*;
44#[doc(hidden)]
45pub mod uuid;
46pub use uuid::*;
47#[doc(hidden)]
48pub mod variant;
49pub use variant::*;
50#[doc(hidden)]
51pub mod rfc3339;
52#[doc(hidden)]
53pub use num_traits::Float;
54pub use regex::Regex;
55#[doc(hidden)]
56pub use source::{SourcePosition, SourcePositionRange};
57
58mod string_interner;
59pub use string_interner::{build_string_interner, intern_string, unintern_string};
60
61// Re-export these types, so they can be used in UDFs without having to import the dbsp crate directly.
62// Perhaps they should be defined in sqllib in the first place?
63pub use dbsp::algebra::{F32, F64};
64use dbsp::{
65    DBData, MapHandle, OrdIndexedZSet, OrdZSet, OutputHandle, ZSetHandle, ZWeight,
66    algebra::{
67        AddByRef, HasOne, HasZero, NegByRef, OrdIndexedZSetFactories, OrdZSetFactories, Semigroup,
68        SemigroupValue, ZRingValue,
69    },
70    circuit::metrics::TOTAL_LATE_RECORDS,
71    dynamic::{DowncastTrait, DynData, Erase},
72    operator::Update,
73    trace::{
74        BatchReader, BatchReaderFactories, Builder, Cursor,
75        ord::{OrdIndexedWSetBuilder, OrdWSetBuilder},
76    },
77    typed_batch::{SpineSnapshot, TypedBatch},
78    utils::*,
79};
80use num::PrimInt;
81use num_traits::Pow;
82use std::marker::PhantomData;
83use std::ops::{Deref, Neg};
84use std::sync::OnceLock;
85use std::{fmt::Debug, sync::atomic::Ordering};
86
87/// Convert a value of a SQL data type to an integer
88/// that preserves ordering.  Used for partitioned_rolling_aggregates
89#[doc(hidden)]
90pub trait ToInteger<T>
91where
92    T: PrimInt,
93{
94    #[doc(hidden)]
95    fn to_integer(&self) -> T;
96}
97
98/// Trait that provides the inverse functionality of the ToInteger trait.
99/// Used for partitioned_rolling_aggregates
100#[doc(hidden)]
101pub trait FromInteger<T>
102where
103    T: PrimInt,
104{
105    #[doc(hidden)]
106    fn from_integer(value: &T) -> Self;
107}
108
109#[doc(hidden)]
110impl<T> ToInteger<T> for T
111where
112    T: PrimInt,
113{
114    #[doc(hidden)]
115    fn to_integer(&self) -> T {
116        *self
117    }
118}
119
120#[doc(hidden)]
121impl<T> FromInteger<T> for T
122where
123    T: PrimInt,
124{
125    #[doc(hidden)]
126    fn from_integer(value: &T) -> Self {
127        *value
128    }
129}
130
131#[doc(hidden)]
132pub type Weight = ZWeight;
133#[doc(hidden)]
134pub type WSet<D> = OrdZSet<D>;
135#[doc(hidden)]
136pub type IndexedWSet<K, D> = OrdIndexedZSet<K, D>;
137
138// Macro to create variants of a function with 1 argument
139// If there exists a function is f_(x: T) -> S, this creates a function
140// fN(x: Option<T>) -> Option<S>, defined as
141// fN(x) { let x = x?; Some(f_(x)) }.
142macro_rules! some_function1 {
143    ($func_name:ident, $arg_type:ty, $ret_type:ty) => {
144        ::paste::paste! {
145            #[doc(hidden)]
146            pub fn [<$func_name N>]( arg: Option<$arg_type> ) -> Option<$ret_type> {
147                let arg = arg?;
148                Some([<$func_name _>](arg))
149            }
150        }
151    };
152}
153
154pub(crate) use some_function1;
155
156// Macro to create variants of a function with 1 argument
157// If there exists a function is f_type(x: T) -> S, this creates a function
158// f_typeN(x: Option<T>) -> Option<S>
159// { let x = x?; Some(f_type(x)) }.
160macro_rules! some_polymorphic_function1 {
161    ($func_name:ident $(< $( const $var : ident : $ty: ty),* >)?, $type_name: ident, $arg_type:ty, $ret_type:ty) => {
162        ::paste::paste! {
163            #[doc(hidden)]
164            pub fn [<$func_name _ $type_name N>] $(< $( const $var : $ty ),* >)? ( arg: Option<$arg_type> ) -> Option<$ret_type> {
165                let arg = arg?;
166                Some([<$func_name _ $type_name >] $(:: < $($var),* >)? (arg))
167            }
168        }
169    };
170}
171
172pub(crate) use some_polymorphic_function1;
173
174// Macro to create variants of a function with 2 arguments
175// If there exists a function is f__(x: T, y: S) -> U, this creates
176// three functions:
177// - f_N(x: T, y: Option<S>) -> Option<U>
178// - fN_(x: Option<T>, y: S) -> Option<U>
179// - fNN(x: Option<T>, y: Option<S>) -> Option<U>
180// The resulting functions return Some only if all arguments are 'Some'.
181macro_rules! some_function2 {
182    ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $ret_type:ty) => {
183        ::paste::paste! {
184            #[doc(hidden)]
185            pub fn [<$func_name NN>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1> ) -> Option<$ret_type> {
186                let arg0 = arg0?;
187                let arg1 = arg1?;
188                Some([<$func_name __>](arg0, arg1))
189            }
190
191            #[doc(hidden)]
192            pub fn [<$func_name _N>]( arg0: $arg_type0, arg1: Option<$arg_type1> ) -> Option<$ret_type> {
193                let arg1 = arg1?;
194                Some([<$func_name __>](arg0, arg1))
195            }
196
197            #[doc(hidden)]
198            pub fn [<$func_name N_>]( arg0: Option<$arg_type0>, arg1: $arg_type1 ) -> Option<$ret_type> {
199                let arg0 = arg0?;
200                Some([<$func_name __>](arg0, arg1))
201            }
202        }
203    }
204}
205
206pub(crate) use some_function2;
207
208// Macro to create variants of a polymorphic function with 2 arguments
209// If there exists a function is f_type1_type2(x: T, y: S) -> U, this
210// creates three functions:
211// - f_type1_type2N(x: T, y: Option<S>) -> Option<U>
212// - f_type1N_type2(x: Option<T>, y: S) -> Option<U>
213// - f_type1N_type2N(x: Option<T>, y: Option<S>) -> Option<U>
214// The resulting functions return Some only if all arguments are 'Some'.
215macro_rules! some_polymorphic_function2 {
216    ($func_name:ident  $(< $( const $var:ident : $ty: ty),* >)?, $type_name0: ident, $arg_type0:ty, $type_name1: ident, $arg_type1:ty, $ret_type:ty) => {
217        ::paste::paste! {
218            #[doc(hidden)]
219            pub fn [<$func_name _$type_name0 _ $type_name1 N>] $(< $( const $var : $ty),* >)? ( arg0: $arg_type0, arg1: Option<$arg_type1> ) -> Option<$ret_type> {
220                let arg1 = arg1?;
221                Some([<$func_name _ $type_name0 _ $type_name1>] $(:: < $($var),* >)? (arg0, arg1))
222            }
223
224            #[doc(hidden)]
225            pub fn [<$func_name _ $type_name0 N _ $type_name1>] $(< $( const $var : $ty),* >)? ( arg0: Option<$arg_type0>, arg1: $arg_type1 ) -> Option<$ret_type> {
226                let arg0 = arg0?;
227                Some([<$func_name _ $type_name0 _ $type_name1>] $(:: < $($var),* >)? (arg0, arg1))
228            }
229
230            #[doc(hidden)]
231            pub fn [<$func_name _ $type_name0 N _ $type_name1 N>] $(< $( const $var : $ty),* >)? ( arg0: Option<$arg_type0>, arg1: Option<$arg_type1> ) -> Option<$ret_type> {
232                let arg0 = arg0?;
233                let arg1 = arg1?;
234                Some([<$func_name _ $type_name0 _ $type_name1>] $(:: < $($var),* >)? (arg0, arg1))
235            }
236        }
237    }
238}
239
240pub(crate) use some_polymorphic_function2;
241
242// If there exists a function is f_t1_t2_t3(x: T, y: S, z: V) -> U, this creates
243// seven functions:
244// - f_t1_t2_t3N(x: T, y: S, z: Option<V>) -> Option<U>
245// - f_t1_t2N_t2(x: T, y: Option<S>, z: V) -> Option<U>
246// - etc.
247// The resulting functions return Some only if all arguments are 'Some'.
248macro_rules! some_polymorphic_function3 {
249    ($func_name:ident,
250     $type_name0: ident, $arg_type0:ty,
251     $type_name1: ident, $arg_type1:ty,
252     $type_name2: ident, $arg_type2: ty,
253     $ret_type:ty) => {
254        ::paste::paste! {
255            #[doc(hidden)]
256            pub fn [<$func_name _ $type_name0 _ $type_name1 _ $type_name2 N>](
257                arg0: $arg_type0,
258                arg1: $arg_type1,
259                arg2: Option<$arg_type2>
260            ) -> Option<$ret_type> {
261                let arg2 = arg2?;
262                Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2))
263            }
264
265            #[doc(hidden)]
266            pub fn [<$func_name _ $type_name0 _ $type_name1 N _ $type_name2>](
267                arg0: $arg_type0,
268                arg1: Option<$arg_type1>,
269                arg2: $arg_type2
270            ) -> Option<$ret_type> {
271                let arg1 = arg1?;
272                Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2))
273            }
274
275            #[doc(hidden)]
276            pub fn [<$func_name _ $type_name0 _ $type_name1 N _ $type_name2 N>](
277                arg0: $arg_type0,
278                arg1: Option<$arg_type1>,
279                arg2: Option<$arg_type2>
280            ) -> Option<$ret_type> {
281                let arg1 = arg1?;
282                let arg2 = arg2?;
283                Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2))
284            }
285
286            #[doc(hidden)]
287            pub fn [<$func_name _ $type_name0 N _ $type_name1 _ $type_name2>](
288                arg0: Option<$arg_type0>,
289                arg1: $arg_type1,
290                arg2: $arg_type2
291            ) -> Option<$ret_type> {
292                let arg0 = arg0?;
293                Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2))
294            }
295
296            #[doc(hidden)]
297            pub fn [<$func_name _ $type_name0 N _ $type_name1 _ $type_name2 N>](
298                arg0: Option<$arg_type0>,
299                arg1: $arg_type1,
300                arg2: Option<$arg_type2>
301            ) -> Option<$ret_type> {
302                let arg0 = arg0?;
303                let arg2 = arg2?;
304                Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2))
305            }
306
307            #[doc(hidden)]
308            pub fn [<$func_name _ $type_name0 N _ $type_name1 N _ $type_name2>](
309                arg0: Option<$arg_type0>,
310                arg1: Option<$arg_type1>,
311                arg2: $arg_type2
312            ) -> Option<$ret_type> {
313                let arg0 = arg0?;
314                let arg1 = arg1?;
315                Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2))
316            }
317
318            #[doc(hidden)]
319            pub fn [<$func_name _ $type_name0 N _ $type_name1 N _ $type_name2 N>](
320                arg0: Option<$arg_type0>,
321                arg1: Option<$arg_type1>,
322                arg2: Option<$arg_type2>
323            ) -> Option<$ret_type> {
324                let arg0 = arg0?;
325                let arg1 = arg1?;
326                let arg2 = arg2?;
327                Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2))
328            }
329        }
330    };
331}
332
333pub(crate) use some_polymorphic_function3;
334
335// If there exists a function is f___(x: T, y: S, z: V) -> U, this creates
336// seven functions:
337// - f__N(x: T, y: S, z: Option<V>) -> Option<U>
338// - f_N_(x: T, y: Option<S>, z: V) -> Option<U>
339// - etc.
340// The resulting functions return Some only if all arguments are 'Some'.
341macro_rules! some_function3 {
342    ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $arg_type2: ty, $ret_type:ty) => {
343        ::paste::paste! {
344            #[doc(hidden)]
345            pub fn [<$func_name __N>]( arg0: $arg_type0, arg1: $arg_type1, arg2: Option<$arg_type2> ) -> Option<$ret_type> {
346                let arg2 = arg2?;
347                Some([<$func_name ___>](arg0, arg1, arg2))
348            }
349
350            #[doc(hidden)]
351            pub fn [<$func_name _N_>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: $arg_type2 ) -> Option<$ret_type> {
352                let arg1 = arg1?;
353                Some([<$func_name ___>](arg0, arg1, arg2))
354            }
355
356            #[doc(hidden)]
357            pub fn [<$func_name _NN>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: Option<$arg_type2> ) -> Option<$ret_type> {
358                let arg1 = arg1?;
359                let arg2 = arg2?;
360                Some([<$func_name ___>](arg0, arg1, arg2))
361            }
362
363            #[doc(hidden)]
364            pub fn [<$func_name N__>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: $arg_type2 ) -> Option<$ret_type> {
365                let arg0 = arg0?;
366                Some([<$func_name ___>](arg0, arg1, arg2))
367            }
368
369            #[doc(hidden)]
370            pub fn [<$func_name N_N>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: Option<$arg_type2> ) -> Option<$ret_type> {
371                let arg0 = arg0?;
372                let arg2 = arg2?;
373                Some([<$func_name ___>](arg0, arg1, arg2))
374            }
375
376            #[doc(hidden)]
377            pub fn [<$func_name NN_>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: $arg_type2 ) -> Option<$ret_type> {
378                let arg0 = arg0?;
379                let arg1 = arg1?;
380                Some([<$func_name ___>](arg0, arg1, arg2))
381            }
382
383            #[doc(hidden)]
384            pub fn [<$func_name NNN>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: Option<$arg_type2> ) -> Option<$ret_type> {
385                let arg0 = arg0?;
386                let arg1 = arg1?;
387                let arg2 = arg2?;
388                Some([<$func_name ___>](arg0, arg1, arg2))
389            }
390        }
391    }
392}
393
394pub(crate) use some_function3;
395
396// Macro to create variants of a function with 4 arguments
397// If there exists a function is f____(x: T, y: S, z: V, w: W) -> U, this
398// creates fifteen functions:
399// - f___N(x: T, y: S, z: V, w: Option<W>) -> Option<U>
400// - f__N_(x: T, y: S, z: Option<V>, w: W) -> Option<U>
401// - etc.
402// The resulting functions return Some only if all arguments are 'Some'.
403macro_rules! some_function4 {
404    ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $arg_type2: ty, $arg_type3: ty, $ret_type:ty) => {
405        ::paste::paste! {
406            #[doc(hidden)]
407            pub fn [<$func_name ___N>]( arg0: $arg_type0, arg1: $arg_type1, arg2: $arg_type2, arg3: Option<$arg_type3> ) -> Option<$ret_type> {
408                let arg3 = arg3?;
409                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
410            }
411
412            #[doc(hidden)]
413            pub fn [<$func_name __N_>]( arg0: $arg_type0, arg1: $arg_type1, arg2: Option<$arg_type2>, arg3: $arg_type3 ) -> Option<$ret_type> {
414                let arg2 = arg2?;
415                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
416            }
417
418            #[doc(hidden)]
419            pub fn [<$func_name __NN>]( arg0: $arg_type0, arg1: $arg_type1, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> {
420                let arg2 = arg2?;
421                let arg3 = arg3?;
422                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
423            }
424
425            #[doc(hidden)]
426            pub fn [<$func_name _N__>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: $arg_type2, arg3: $arg_type3 ) -> Option<$ret_type> {
427                let arg1 = arg1?;
428                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
429            }
430
431            #[doc(hidden)]
432            pub fn [<$func_name _N_N>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: $arg_type2, arg3: Option<$arg_type3> ) -> Option<$ret_type> {
433                let arg1 = arg1?;
434                let arg3 = arg3?;
435                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
436            }
437
438            #[doc(hidden)]
439            pub fn [<$func_name _NN_>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: $arg_type3 ) -> Option<$ret_type> {
440                let arg1 = arg1?;
441                let arg2 = arg2?;
442                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
443            }
444
445            #[doc(hidden)]
446            pub fn [<$func_name _NNN>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> {
447                let arg1 = arg1?;
448                let arg2 = arg2?;
449                let arg3 = arg3?;
450                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
451            }
452
453            #[doc(hidden)]
454            pub fn [<$func_name N___>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: $arg_type2, arg3: $arg_type3 ) -> Option<$ret_type> {
455                let arg0 = arg0?;
456                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
457            }
458
459            #[doc(hidden)]
460            pub fn [<$func_name N__N>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> {
461                let arg0 = arg0?;
462                let arg2 = arg2?;
463                let arg3 = arg3?;
464                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
465            }
466
467            #[doc(hidden)]
468            pub fn [<$func_name N_N_>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: $arg_type2, arg3: $arg_type3 ) -> Option<$ret_type> {
469                let arg0 = arg0?;
470                let arg1 = arg1?;
471                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
472            }
473
474            #[doc(hidden)]
475            pub fn [<$func_name N_NN>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> {
476                let arg0 = arg0?;
477                let arg1 = arg1?;
478                let arg2 = arg2?;
479                let arg3 = arg3?;
480                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
481            }
482
483            #[doc(hidden)]
484            pub fn [<$func_name NN__>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: $arg_type2, arg3: $arg_type3 ) -> Option<$ret_type> {
485                let arg0 = arg0?;
486                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
487            }
488
489            #[doc(hidden)]
490            pub fn [<$func_name NN_N>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> {
491                let arg0 = arg0?;
492                let arg2 = arg2?;
493                let arg3 = arg3?;
494                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
495            }
496
497            #[doc(hidden)]
498            pub fn [<$func_name NNN_>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: $arg_type3 ) -> Option<$ret_type> {
499                let arg0 = arg0?;
500                let arg1 = arg1?;
501                let arg2 = arg2?;
502                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
503            }
504
505            #[doc(hidden)]
506            pub fn [<$func_name NNNN>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> {
507                let arg0 = arg0?;
508                let arg1 = arg1?;
509                let arg2 = arg2?;
510                let arg3 = arg3?;
511                Some([<$func_name ____>](arg0, arg1, arg2, arg3))
512            }
513        }
514    }
515}
516
517pub(crate) use some_function4;
518
519// Macro to create variants of a function with 2 arguments
520// optimized for the implementation of arithmetic operators.
521// Assuming there exists a function is f__(x: T, y: T) -> U, this creates
522// three functions:
523// - f_tN_t(x: T, y: Option<T>) -> Option<U>
524// - f_t_tN(x: Option<T>, y: T) -> Option<U>
525// - f_tN_tN(x: Option<T>, y: Option<T>) -> Option<U>
526// The resulting functions return Some only if all arguments are 'Some'.
527macro_rules! some_existing_operator {
528    ($func_name: ident $(< $( const $var:ident : $ty: ty),* >)?, $short_name: ident, $arg_type: ty, $ret_type: ty) => {
529        ::paste::paste! {
530            #[inline(always)]
531            #[doc(hidden)]
532            pub fn [<$func_name _ $short_name N _ $short_name N>] $(< $( const $var : $ty ),* >)? ( arg0: Option<$arg_type>, arg1: Option<$arg_type> ) -> Option<$ret_type> {
533                let arg0 = arg0?;
534                let arg1 = arg1?;
535                Some([<$func_name _ $short_name _ $short_name>] $(:: < $($var),* >)? (arg0, arg1))
536            }
537
538            #[inline(always)]
539            #[doc(hidden)]
540            pub fn [<$func_name _ $short_name _ $short_name N>] $(< $( const $var : $ty ),* >)? ( arg0: $arg_type, arg1: Option<$arg_type> ) -> Option<$ret_type> {
541                let arg1 = arg1?;
542                Some([<$func_name _ $short_name _ $short_name>] $(:: < $($var),* >)? (arg0, arg1))
543            }
544
545            #[inline(always)]
546            #[doc(hidden)]
547            pub fn [<$func_name _ $short_name N _ $short_name>] $(< $( const $var : $ty ),* >)? ( arg0: Option<$arg_type>, arg1: $arg_type ) -> Option<$ret_type> {
548                let arg0 = arg0?;
549                Some([<$func_name _ $short_name _ $short_name>] $(:: < $($var),* >)? (arg0, arg1))
550            }
551        }
552    }
553}
554
555pub(crate) use some_existing_operator;
556
557// Macro to create variants of a function with 2 arguments
558// optimized for the implementation of arithmetic operators.
559// Assuming there exists a function is f(x: T, y: T) -> U, this creates
560// four functions:
561// - f_t_t(x: T, y: T) -> U
562// - f_tN_t(x: T, y: Option<T>) -> Option<U>
563// - f_t_tN(x: Option<T>, y: T) -> Option<U>
564// - f_tN_tN(x: Option<T>, y: Option<T>) -> Option<U>
565// The resulting functions return Some only if all arguments are 'Some'.
566//
567// Has two variants:
568// - Takes the name of the existing function, the generated functions will have
569// this prefix
570// - Takes the name of the existing function, and the prefix for the generated
571// functions
572macro_rules! some_operator {
573    ($func_name: ident $(< $( const $var:ident : $ty: ty),* >)?, $short_name: ident, $arg_type: ty, $ret_type: ty) => {
574        ::paste::paste! {
575            #[doc(hidden)]
576            #[inline(always)]
577            pub fn [<$func_name _ $short_name _ $short_name >] $(< $(const $var : $ty),* >)?  ( arg0: $arg_type, arg1: $arg_type ) -> $ret_type {
578                $func_name $(:: < $($var),* >)? (arg0, arg1)
579            }
580
581            some_existing_operator!($func_name $(< $( const $var : $ty),* >)?, $short_name, $arg_type, $ret_type);
582        }
583    };
584
585    ($func_name: ident $(< $( const $var:ident : $ty: ty),* >)?, $new_func_name: ident, $short_name: ident, $arg_type: ty, $ret_type: ty) => {
586        ::paste::paste! {
587            #[doc(hidden)]
588            #[inline(always)]
589            pub fn [<$new_func_name _ $short_name _ $short_name >] $(< $(const $var : $ty ),* >)? ( arg0: $arg_type, arg1: $arg_type ) -> $ret_type {
590                $func_name $(:: < $($var),* >)? (arg0, arg1)
591            }
592
593            some_existing_operator!($new_func_name $(< $( const $var : $ty),* >)?, $short_name, $arg_type, $ret_type);
594        }
595    }
596}
597
598pub(crate) use some_operator;
599
600macro_rules! for_all_int_operator {
601    ($func_name: ident) => {
602        some_operator!($func_name, i8, i8, i8);
603        some_operator!($func_name, i16, i16, i16);
604        some_operator!($func_name, i32, i32, i32);
605        some_operator!($func_name, i64, i64, i64);
606        some_operator!($func_name, i128, i128, i128);
607        some_operator!($func_name, u8, u8, u8);
608        some_operator!($func_name, u16, u16, u16);
609        some_operator!($func_name, u32, u32, u32);
610        some_operator!($func_name, u64, u64, u64);
611    };
612}
613pub(crate) use for_all_int_operator;
614
615#[doc(hidden)]
616#[inline(always)]
617pub fn wrap_bool(b: Option<bool>) -> bool {
618    b.unwrap_or_default()
619}
620
621#[doc(hidden)]
622#[inline(always)]
623pub fn or_b_b<F>(left: bool, right: F) -> bool
624where
625    F: Fn() -> bool,
626{
627    left || right()
628}
629
630#[doc(hidden)]
631#[inline(always)]
632pub fn or_bN_b<F>(left: Option<bool>, right: F) -> Option<bool>
633where
634    F: Fn() -> bool,
635{
636    match left {
637        Some(l) => Some(l || right()),
638        None => match right() {
639            true => Some(true),
640            _ => None,
641        },
642    }
643}
644
645#[doc(hidden)]
646#[inline(always)]
647pub fn or_b_bN<F>(left: bool, right: F) -> Option<bool>
648where
649    F: Fn() -> Option<bool>,
650{
651    match left {
652        false => right(),
653        true => Some(true),
654    }
655}
656
657#[doc(hidden)]
658#[inline(always)]
659pub fn or_bN_bN<F>(left: Option<bool>, right: F) -> Option<bool>
660where
661    F: Fn() -> Option<bool>,
662{
663    match left {
664        None => match right() {
665            Some(true) => Some(true),
666            _ => None,
667        },
668        Some(false) => right(),
669        Some(true) => Some(true),
670    }
671}
672
673// OR and AND are special, they can't be generated by rules
674
675#[doc(hidden)]
676#[inline(always)]
677pub fn and_b_b<F>(left: bool, right: F) -> bool
678where
679    F: Fn() -> bool,
680{
681    left && right()
682}
683
684#[doc(hidden)]
685#[inline(always)]
686pub fn and_bN_b<F>(left: Option<bool>, right: F) -> Option<bool>
687where
688    F: Fn() -> bool,
689{
690    match left {
691        Some(false) => Some(false),
692        Some(true) => Some(right()),
693        None => match right() {
694            false => Some(false),
695            _ => None,
696        },
697    }
698}
699
700#[doc(hidden)]
701#[inline(always)]
702pub fn and_b_bN<F>(left: bool, right: F) -> Option<bool>
703where
704    F: Fn() -> Option<bool>,
705{
706    match left {
707        false => Some(false),
708        true => right(),
709    }
710}
711
712#[doc(hidden)]
713#[inline(always)]
714pub fn and_bN_bN<F>(left: Option<bool>, right: F) -> Option<bool>
715where
716    F: Fn() -> Option<bool>,
717{
718    match left {
719        Some(false) => Some(false),
720        Some(true) => right(),
721        None => match right() {
722            Some(false) => Some(false),
723            _ => None,
724        },
725    }
726}
727
728#[doc(hidden)]
729#[inline(always)]
730pub fn is_null<T>(value: Option<T>) -> bool {
731    value.is_none()
732}
733
734#[doc(hidden)]
735#[inline(always)]
736pub fn indicator<T, R>(value: &Option<T>) -> R
737where
738    R: HasZero + HasOne,
739{
740    match value {
741        None => R::zero(),
742        Some(_) => R::one(),
743    }
744}
745
746//////////////////////////////////////////
747
748#[doc(hidden)]
749#[inline(always)]
750pub fn abs_i8(left: i8) -> i8 {
751    left.abs()
752}
753
754#[doc(hidden)]
755#[inline(always)]
756pub fn abs_i16(left: i16) -> i16 {
757    left.abs()
758}
759
760#[doc(hidden)]
761#[inline(always)]
762pub fn abs_i32(left: i32) -> i32 {
763    left.abs()
764}
765
766#[doc(hidden)]
767#[inline(always)]
768pub fn abs_i64(left: i64) -> i64 {
769    left.abs()
770}
771
772#[doc(hidden)]
773#[inline(always)]
774pub fn abs_i128(left: i128) -> i128 {
775    left.abs()
776}
777
778#[doc(hidden)]
779#[inline(always)]
780pub fn abs_f(left: F32) -> F32 {
781    left.abs()
782}
783
784#[doc(hidden)]
785#[inline(always)]
786pub fn abs_d(left: F64) -> F64 {
787    left.abs()
788}
789
790#[doc(hidden)]
791#[inline(always)]
792pub fn abs_u8(left: u8) -> u8 {
793    left
794}
795
796#[doc(hidden)]
797#[inline(always)]
798pub fn abs_u16(left: u16) -> u16 {
799    left
800}
801
802#[doc(hidden)]
803#[inline(always)]
804pub fn abs_u32(left: u32) -> u32 {
805    left
806}
807
808#[doc(hidden)]
809#[inline(always)]
810pub fn abs_u64(left: u64) -> u64 {
811    left
812}
813
814#[doc(hidden)]
815#[inline(always)]
816pub fn abs_u128(left: u128) -> u128 {
817    left
818}
819
820some_polymorphic_function1!(abs, i8, i8, i8);
821some_polymorphic_function1!(abs, i16, i16, i16);
822some_polymorphic_function1!(abs, i32, i32, i32);
823some_polymorphic_function1!(abs, i64, i64, i64);
824some_polymorphic_function1!(abs, i128, i128, i128);
825some_polymorphic_function1!(abs, f, F32, F32);
826some_polymorphic_function1!(abs, d, F64, F64);
827some_polymorphic_function1!(abs, u8, u8, u8);
828some_polymorphic_function1!(abs, u16, u16, u16);
829some_polymorphic_function1!(abs, u32, u32, u32);
830some_polymorphic_function1!(abs, u64, u64, u64);
831some_polymorphic_function1!(abs, u128, u128, u128);
832
833#[inline(always)]
834#[doc(hidden)]
835pub fn sign_i8(x: i8) -> i8 {
836    if x == 0 { x } else { x.signum() }
837}
838
839#[inline(always)]
840#[doc(hidden)]
841pub fn sign_i16(x: i16) -> i16 {
842    if x == 0 { x } else { x.signum() }
843}
844
845#[inline(always)]
846#[doc(hidden)]
847pub fn sign_i32(x: i32) -> i32 {
848    if x == 0 { x } else { x.signum() }
849}
850
851#[inline(always)]
852#[doc(hidden)]
853pub fn sign_i64(x: i64) -> i64 {
854    if x == 0 { x } else { x.signum() }
855}
856
857#[inline(always)]
858#[doc(hidden)]
859pub fn sign_i128(x: i128) -> i128 {
860    if x == 0 { x } else { x.signum() }
861}
862
863#[inline(always)]
864#[doc(hidden)]
865pub fn sign_u8(x: u8) -> u8 {
866    if x == 0 { x } else { 1 }
867}
868
869#[inline(always)]
870#[doc(hidden)]
871pub fn sign_u16(x: u16) -> u16 {
872    if x == 0 { x } else { 1 }
873}
874
875#[inline(always)]
876#[doc(hidden)]
877pub fn sign_u32(x: u32) -> u32 {
878    if x == 0 { x } else { 1 }
879}
880
881#[inline(always)]
882#[doc(hidden)]
883pub fn sign_u64(x: u64) -> u64 {
884    if x == 0 { x } else { 1 }
885}
886
887#[inline(always)]
888#[doc(hidden)]
889pub fn sign_u128(x: u128) -> u128 {
890    if x == 0 { x } else { 1 }
891}
892
893some_polymorphic_function1!(sign, i8, i8, i8);
894some_polymorphic_function1!(sign, i16, i16, i16);
895some_polymorphic_function1!(sign, i32, i32, i32);
896some_polymorphic_function1!(sign, i64, i64, i64);
897some_polymorphic_function1!(sign, i128, i128, i128);
898some_polymorphic_function1!(sign, u8, u8, u8);
899some_polymorphic_function1!(sign, u16, u16, u16);
900some_polymorphic_function1!(sign, u32, u32, u32);
901some_polymorphic_function1!(sign, u64, u64, u64);
902some_polymorphic_function1!(sign, u128, u128, u128);
903
904#[doc(hidden)]
905#[inline(always)]
906pub const fn is_true_b_(left: bool) -> bool {
907    left
908}
909
910#[doc(hidden)]
911#[inline(always)]
912pub const fn is_true_bN_(left: Option<bool>) -> bool {
913    matches!(left, Some(true))
914}
915
916#[doc(hidden)]
917#[inline(always)]
918pub fn is_false_b_(left: bool) -> bool {
919    !left
920}
921
922#[doc(hidden)]
923#[inline(always)]
924pub const fn is_false_bN_(left: Option<bool>) -> bool {
925    matches!(left, Some(false))
926}
927
928#[doc(hidden)]
929#[inline(always)]
930pub const fn is_not_true_b_(left: bool) -> bool {
931    !left
932}
933
934#[doc(hidden)]
935#[inline(always)]
936pub const fn is_not_true_bN_(left: Option<bool>) -> bool {
937    match left {
938        Some(true) => false,
939        Some(false) => true,
940        _ => true,
941    }
942}
943
944#[doc(hidden)]
945#[inline(always)]
946pub const fn is_not_false_b_(left: bool) -> bool {
947    left
948}
949
950#[doc(hidden)]
951#[inline(always)]
952pub const fn is_not_false_bN_(left: Option<bool>) -> bool {
953    match left {
954        Some(true) => true,
955        Some(false) => false,
956        _ => true,
957    }
958}
959
960#[doc(hidden)]
961#[inline(always)]
962pub fn is_distinct__<T>(left: T, right: T) -> bool
963where
964    T: Eq,
965{
966    left != right
967}
968
969#[doc(hidden)]
970#[inline(always)]
971pub fn is_distinct_N_N<T>(left: Option<T>, right: Option<T>) -> bool
972where
973    T: Eq,
974{
975    left != right
976}
977
978#[doc(hidden)]
979#[inline(always)]
980pub fn is_distinct__N<T>(left: T, right: Option<T>) -> bool
981where
982    T: Eq,
983{
984    match right {
985        Some(b) => left != b,
986        None => true,
987    }
988}
989
990#[doc(hidden)]
991#[inline(always)]
992pub fn is_distinct_N_<T>(left: Option<T>, right: T) -> bool
993where
994    T: Eq,
995{
996    match left {
997        Some(a) => a != right,
998        None => true,
999    }
1000}
1001
1002#[doc(hidden)]
1003pub fn weighted_push<T, W>(vec: &mut Vec<T>, value: &T, weight: W)
1004where
1005    W: ZRingValue,
1006    T: Clone,
1007{
1008    let mut w = weight;
1009    let negone = W::one().neg();
1010    while w != W::zero() {
1011        vec.push(value.clone());
1012        w = w.add_by_ref(&negone);
1013    }
1014}
1015
1016#[doc(hidden)]
1017pub fn power_i32_i32(left: i32, right: i32) -> F64 {
1018    (left as f64).pow(right).into()
1019}
1020
1021some_polymorphic_function2!(power, i32, i32, i32, i32, F64);
1022
1023////////////////////////////////////////////////
1024
1025// Functions called by 'writelog'
1026#[doc(hidden)]
1027pub fn dump<T>(prefix: SqlString, data: &T) -> T
1028where
1029    T: Debug + Clone,
1030{
1031    println!("{}: {:?}", prefix.str(), data);
1032    data.clone()
1033}
1034
1035#[doc(hidden)]
1036pub fn print(str: SqlString) {
1037    print!("{}", str.str())
1038}
1039
1040#[doc(hidden)]
1041pub fn print_opt(str: Option<SqlString>) {
1042    match str {
1043        None => print!("NULL"),
1044        Some(x) => print!("{}", x.str()),
1045    }
1046}
1047
1048#[doc(hidden)]
1049pub fn zset_map<D, T, F>(data: &WSet<D>, mapper: F) -> WSet<T>
1050where
1051    D: DBData + 'static,
1052    T: DBData + 'static,
1053    F: Fn(&D) -> T,
1054{
1055    let mut tuples = Vec::new();
1056    let mut cursor = data.cursor();
1057    while cursor.key_valid() {
1058        let item = unsafe { cursor.key().downcast::<D>() };
1059        let data = mapper(item);
1060        let weight = unsafe { *cursor.weight().downcast::<ZWeight>() };
1061        tuples.push(Tup2(Tup2(data, ()), weight));
1062        cursor.step_key();
1063    }
1064    WSet::from_tuples((), tuples)
1065}
1066
1067#[doc(hidden)]
1068pub fn late() {
1069    TOTAL_LATE_RECORDS.fetch_add(1, Ordering::Relaxed);
1070}
1071
1072#[doc(hidden)]
1073pub fn zset_filter_comparator<D, T, F>(data: &WSet<D>, value: &T, comparator: F) -> WSet<D>
1074where
1075    D: DBData + 'static,
1076    T: 'static + Debug,
1077    F: Fn(&D, &T) -> bool,
1078{
1079    let factories = OrdZSetFactories::new::<D, (), ZWeight>();
1080
1081    let mut builder = OrdWSetBuilder::with_capacity(&factories, data.len(), data.len());
1082
1083    let mut cursor = data.cursor();
1084    while cursor.key_valid() {
1085        let item = unsafe { cursor.key().downcast::<D>() };
1086        if comparator(item, value) {
1087            // println!("controlled_filter accepts={:?}", item);
1088            builder.push_val_diff(().erase(), cursor.weight());
1089            builder.push_key(cursor.key());
1090        } else {
1091            late();
1092        }
1093        cursor.step_key();
1094    }
1095    TypedBatch::new(builder.done())
1096}
1097
1098#[doc(hidden)]
1099pub fn indexed_zset_filter_comparator<K, D, T, F>(
1100    data: &IndexedWSet<K, D>,
1101    value: &T,
1102    comparator: F,
1103) -> IndexedWSet<K, D>
1104where
1105    K: DBData + Erase<DynData>,
1106    D: DBData + Erase<DynData>,
1107    T: 'static,
1108    F: Fn((&K, &D), &T) -> bool,
1109{
1110    let factories = OrdIndexedZSetFactories::new::<K, D, ZWeight>();
1111    let mut builder =
1112        OrdIndexedWSetBuilder::with_capacity(&factories, data.key_count(), data.len());
1113
1114    let mut cursor = data.cursor();
1115    while cursor.key_valid() {
1116        let key = unsafe { cursor.key().downcast::<K>() }.clone();
1117        let mut any_values = false;
1118        while cursor.val_valid() {
1119            let w = *cursor.weight().deref();
1120            let item = unsafe { cursor.val().downcast::<D>() };
1121            if comparator((&key, item), value) {
1122                builder.push_val_diff(item.erase(), w.erase());
1123                any_values = true;
1124            } else {
1125                late();
1126            }
1127            cursor.step_val();
1128        }
1129        if any_values {
1130            builder.push_key(cursor.key());
1131        }
1132        cursor.step_key();
1133    }
1134    TypedBatch::new(builder.done())
1135}
1136
1137#[doc(hidden)]
1138pub fn append_to_map_handle<K, V, U>(
1139    data: &WSet<V>,
1140    handle: &MapHandle<K, V, U>,
1141    key_f: fn(&V) -> K,
1142) where
1143    K: DBData,
1144    V: DBData,
1145    U: DBData,
1146{
1147    let mut cursor = data.cursor();
1148    while cursor.key_valid() {
1149        let w = *cursor.weight().deref();
1150        if w.is_zero() {
1151            continue;
1152        }
1153        if !w.ge0() {
1154            let key = unsafe { cursor.key().downcast::<V>() };
1155            handle.push(key_f(&key.clone()), Update::Delete);
1156        } else {
1157            let key = unsafe { cursor.key().downcast::<V>() };
1158            handle.push(key_f(&key.clone()), Update::Insert(key.clone()));
1159        }
1160        cursor.step_key();
1161    }
1162}
1163
1164#[doc(hidden)]
1165pub fn append_to_collection_handle<K>(data: &WSet<K>, handle: &ZSetHandle<K>)
1166where
1167    K: DBData,
1168{
1169    let mut cursor = data.cursor();
1170    while cursor.key_valid() {
1171        handle.push(
1172            unsafe { cursor.key().downcast::<K>() }.clone(),
1173            *cursor.weight().deref(),
1174        );
1175        cursor.step_key();
1176    }
1177}
1178
1179#[doc(hidden)]
1180pub fn read_output_handle<K>(handle: &OutputHandle<WSet<K>>) -> WSet<K>
1181where
1182    K: DBData,
1183{
1184    handle.consolidate()
1185}
1186
1187#[doc(hidden)]
1188pub fn read_output_spine<K>(handle: &OutputHandle<SpineSnapshot<WSet<K>>>) -> WSet<K>
1189where
1190    K: DBData,
1191{
1192    handle.concat().consolidate()
1193}
1194
1195// Check that two zsets are equal.  If yes, returns true.
1196// If not, print a diff of the zsets and returns false.
1197// Assumes that the zsets are positive (all weights are positive).
1198#[doc(hidden)]
1199pub fn must_equal<K>(left: &WSet<K>, right: &WSet<K>) -> bool
1200where
1201    K: DBData + Clone,
1202{
1203    // println!("L={:?}\nR={:?}\n", left, right);
1204    let diff = left.add_by_ref(&right.neg_by_ref());
1205    if diff.is_zero() {
1206        return true;
1207    }
1208    let mut cursor = diff.cursor();
1209    let mut shown = 0;
1210    let mut left = 0;
1211    let mut right = 0;
1212    while cursor.key_valid() {
1213        let weight = **cursor.weight();
1214        let key = cursor.key();
1215        if shown < 50 {
1216            if weight.le0() {
1217                println!("R: {:?}x{:?}", key, weight.neg());
1218            } else {
1219                println!("L: {:?}x{:?}", key, weight);
1220            }
1221        } else if weight.le0() {
1222            right += weight.neg();
1223        } else {
1224            left += weight;
1225        }
1226        cursor.step_key();
1227        shown += 1;
1228    }
1229    if left > 0 || right > 0 {
1230        println!("Additional L:{left} and R:{right} rows not shown");
1231    }
1232    false
1233}
1234
1235#[doc(hidden)]
1236pub fn zset_size<K>(set: &WSet<K>) -> i64 {
1237    let mut w = 0;
1238    let mut cursor = set.cursor();
1239    while cursor.key_valid() {
1240        let weight = **cursor.weight();
1241        w += weight;
1242        cursor.step_key();
1243    }
1244    w
1245}
1246
1247//////////////////////// Semigroup implementations
1248
1249#[derive(Clone)]
1250#[doc(hidden)]
1251pub struct DefaultOptSemigroup<T>(PhantomData<T>);
1252
1253#[doc(hidden)]
1254impl<T> Semigroup<Option<T>> for DefaultOptSemigroup<T>
1255where
1256    T: SemigroupValue,
1257{
1258    #[doc(hidden)]
1259    fn combine(left: &Option<T>, right: &Option<T>) -> Option<T> {
1260        match (left, right) {
1261            (None, _) => None,
1262            (_, None) => None,
1263            (Some(x), Some(y)) => Some(x.add_by_ref(y)),
1264        }
1265    }
1266}
1267
1268#[derive(Clone)]
1269#[doc(hidden)]
1270pub struct PairSemigroup<T, R, TS, RS>(PhantomData<(T, R, TS, RS)>);
1271
1272#[doc(hidden)]
1273impl<T, R, TS, RS> Semigroup<Tup2<T, R>> for PairSemigroup<T, R, TS, RS>
1274where
1275    TS: Semigroup<T>,
1276    RS: Semigroup<R>,
1277{
1278    #[doc(hidden)]
1279    fn combine(left: &Tup2<T, R>, right: &Tup2<T, R>) -> Tup2<T, R> {
1280        Tup2::new(
1281            TS::combine(&left.0, &right.0),
1282            RS::combine(&left.1, &right.1),
1283        )
1284    }
1285}
1286
1287#[derive(Clone)]
1288#[doc(hidden)]
1289pub struct TripleSemigroup<T, R, V, TS, RS, VS>(PhantomData<(T, R, V, TS, RS, VS)>);
1290
1291#[doc(hidden)]
1292impl<T, R, V, TS, RS, VS> Semigroup<Tup3<T, R, V>> for TripleSemigroup<T, R, V, TS, RS, VS>
1293where
1294    TS: Semigroup<T>,
1295    RS: Semigroup<R>,
1296    VS: Semigroup<V>,
1297{
1298    #[doc(hidden)]
1299    fn combine(left: &Tup3<T, R, V>, right: &Tup3<T, R, V>) -> Tup3<T, R, V> {
1300        Tup3::new(
1301            TS::combine(&left.0, &right.0),
1302            RS::combine(&left.1, &right.1),
1303            VS::combine(&left.2, &right.2),
1304        )
1305    }
1306}
1307
1308#[doc(hidden)]
1309#[derive(Clone)]
1310pub struct ConcatSemigroup<V>(PhantomData<V>);
1311
1312// Semigroup for the SINGLE_VALUE aggregate
1313#[derive(Clone)]
1314#[doc(hidden)]
1315pub struct SingleSemigroup<T>(PhantomData<T>);
1316
1317#[doc(hidden)]
1318impl<T> Semigroup<Tup2<bool, T>> for SingleSemigroup<Tup2<bool, T>>
1319where
1320    T: Clone,
1321{
1322    #[doc(hidden)]
1323    fn combine(left: &Tup2<bool, T>, right: &Tup2<bool, T>) -> Tup2<bool, T> {
1324        if left.0 && right.0 {
1325            panic!("More than one value in subquery");
1326        }
1327        Tup2::new(
1328            left.0 || right.0,
1329            if left.0 {
1330                left.1.clone()
1331            } else {
1332                right.1.clone()
1333            },
1334        )
1335    }
1336}
1337
1338/// A lazily initialized static value, where the initialized can be a capturing
1339/// closure.
1340///
1341/// This struct is supposed to do the same thing as some other lazy
1342/// Rust types, like std::sync::Lazy, or std::cell::LazyCell: it holds
1343/// a constant value, but which needs to be initialized only on demand
1344/// (because it could panic).  Unfortunately I could not use an
1345/// off-the-shelf struct like the ones mentioned, because the
1346/// initializer is not always `const`.  This implementation separates
1347/// the creation (`new`) from the initialization (`init`).  This
1348/// enables us to use this class to declare `static` Rust values,
1349/// which nevertheless are initialized on first use.  In the
1350/// initializers we actually always use static constant values to, but
1351/// they are sometimes passed through function arguments, so the Rust
1352/// compiler cannot recognize them as such.  For example:
1353/// ```ignore
1354/// // In the main crate:
1355/// pub static SOURCE_MAP_STATIC: OnceLock<SourceMap> = OnceLock::new();
1356/// SOURCE_MAP_STATIC.get_or_init(|| {
1357///      let mut m = SourceMap::new();
1358///           m.insert("0ee9907f", 0, SourcePosition::new(222, 2));
1359///           m.insert("0ee9907f", 1, SourcePosition::new(223, 2));
1360///           m
1361///       });
1362/// let sourceMap = SOURCE_MAP_STATIC.get().unwrap();
1363/// let s3 = create_operator_x(&circuit, Some("0ee9907f"), &sourceMap, &mut catalog, s2);
1364/// ...
1365/// // In the operator crate
1366/// pub fn create_operator_x(
1367///         circuit: &RootCircuit,
1368///         hash: Option<&'static str>,
1369///         sourceMap: &'static SourceMap,  // static lifetime, but not const
1370///         catalog: &mut Catalog,
1371///         i0: &Stream<RootCircuit, WSet<...>>) -> Stream<RootCircuit, ...> {
1372///    static STATIC_4dbc5aebe9c4edea: StaticLazy<Option<SqlDecimal<38, 6>>> = StaticLazy::new();
1373///    STATIC_4dbc5aebe9c4edea.init(move || handle_error_with_position(
1374///               "global", 25, &sourceMap, cast_to_SqlDecimalN_i32N::<38, 6>(Some(1i32));
1375///    ...
1376/// };
1377/// ```
1378/// The function `handle_error_with_position` may panic, so it needs to be lazily evaluated.
1379#[derive(Default)]
1380#[doc(hidden)]
1381pub struct StaticLazy<T: 'static> {
1382    cell: OnceLock<T>,
1383    init: OnceLock<&'static (dyn Fn() -> T + Send + Sync)>,
1384}
1385
1386#[doc(hidden)]
1387impl<T> StaticLazy<T> {
1388    #[doc(hidden)]
1389    pub const fn new() -> Self {
1390        Self {
1391            cell: OnceLock::new(),
1392            init: OnceLock::new(),
1393        }
1394    }
1395
1396    #[doc(hidden)]
1397    pub fn init<F>(&'static self, f: F)
1398    where
1399        F: Fn() -> T + Send + Sync + 'static,
1400    {
1401        if self.cell.get().is_some() {
1402            return;
1403        }
1404        let leaked: &'static (dyn Fn() -> T + Send + Sync) = Box::leak(Box::new(f));
1405        self.init.set(leaked).unwrap_or(());
1406    }
1407
1408    #[doc(hidden)]
1409    fn get(&self) -> &T {
1410        self.cell.get_or_init(|| {
1411            let f = self
1412                .init
1413                .get()
1414                .unwrap_or_else(|| panic!("Initializer not set"));
1415            f()
1416        })
1417    }
1418}
1419
1420#[doc(hidden)]
1421impl<T> Deref for StaticLazy<T> {
1422    type Target = T;
1423
1424    fn deref(&self) -> &Self::Target {
1425        self.get()
1426    }
1427}
1428
1429#[doc(hidden)]
1430// If the data is Ok(None), convert it to Err, other leave it unchanged
1431pub fn unwrap_sql_result<T>(data: SqlResult<Option<T>>) -> SqlResult<T> {
1432    match data {
1433        Err(e) => Err(e),
1434        Ok(None) => Err(SqlRuntimeError::from_strng("NULL result produced")),
1435        Ok(Some(data)) => Ok(data),
1436    }
1437}
1438
1439#[doc(hidden)]
1440pub fn wrap_sql_result<T>(data: T) -> SqlResult<T> {
1441    Ok(data)
1442}