diff --git a/crates/sqllib/src/array.rs b/crates/sqllib/src/array.rs index 815dc0df24..a225874aec 100644 --- a/crates/sqllib/src/array.rs +++ b/crates/sqllib/src/array.rs @@ -1,7 +1,7 @@ // Array operations use crate::error::{SqlResult, SqlRuntimeError}; -use crate::{ConcatSemigroup, Semigroup, Weight, some_function2}; +use crate::{ConcatSemigroup, Semigroup, Weight, some_function1, some_function2}; use dbsp::CmpFunc; use itertools::Itertools; use std::{collections::HashSet, fmt::Debug, hash::Hash, sync::Arc}; @@ -421,13 +421,7 @@ where Arc::new(vector) } -#[doc(hidden)] -pub fn array_reverseN(vector: Option>) -> Option> -where - T: Clone, -{ - Some(array_reverse_(vector?)) -} +some_function1!(array_reverse [T: Clone], Array, Array); #[doc(hidden)] pub fn sort_array(vector: Array, ascending: bool) -> Array @@ -528,13 +522,7 @@ where .into() } -#[doc(hidden)] -pub fn array_compactN(vector: Option>>) -> Option> -where - T: Clone, -{ - Some(array_compact_(vector?)) -} +some_function1!(array_compact [T: Clone], Array>, Array); fn array_insert(vector: Array, value: T, index: usize) -> Array where @@ -639,33 +627,7 @@ where false } -#[doc(hidden)] -pub fn arrays_overlapN_(first: Option>, second: Array) -> Option -where - T: Eq + Hash, -{ - let first = first?; - Some(arrays_overlap__(first, second)) -} - -#[doc(hidden)] -pub fn arrays_overlap_N(first: Array, second: Option>) -> Option -where - T: Eq + Hash, -{ - let second = second?; - Some(arrays_overlap__(first, second)) -} - -#[doc(hidden)] -pub fn arrays_overlapNN(first: Option>, second: Option>) -> Option -where - T: Eq + Hash, -{ - let first = first?; - let second = second?; - Some(arrays_overlap__(first, second)) -} +some_function2!(arrays_overlap [T: Eq + Hash], Array, Array, bool); #[doc(hidden)] pub fn array_agg(accumulator: &mut Vec, value: T, weight: Weight, distinct: bool, keep: bool) @@ -753,33 +715,7 @@ where } } -#[doc(hidden)] -pub fn array_concatN_(left: Option>, right: Array) -> Option> -where - T: Clone, -{ - let left = left?; - Some(array_concat__(left, right)) -} - -#[doc(hidden)] -pub fn array_concat_N(left: Array, right: Option>) -> Option> -where - T: Clone, -{ - let right = right?; - Some(array_concat__(left, right)) -} - -#[doc(hidden)] -pub fn array_concatNN(left: Option>, right: Option>) -> Option> -where - T: Clone, -{ - let left = left?; - let right = right?; - Some(array_concat__(left, right)) -} +some_function2!(array_concat [T: Clone], Array, Array, Array); fn to_set(v: &[T]) -> HashSet<&T> where @@ -801,33 +737,7 @@ where result.into() } -#[doc(hidden)] -pub fn array_exceptN_(left: Option>, right: Array) -> Option> -where - T: Eq + Clone + Hash + Ord + Debug, -{ - let left = left?; - Some(array_except__(left, right)) -} - -#[doc(hidden)] -pub fn array_except_N(left: Array, right: Option>) -> Option> -where - T: Eq + Clone + Hash + Ord + Debug, -{ - let right = right?; - Some(array_except__(left, right)) -} - -#[doc(hidden)] -pub fn array_exceptNN(left: Option>, right: Option>) -> Option> -where - T: Eq + Clone + Hash + Ord + Debug, -{ - let left = left?; - let right = right?; - Some(array_except__(left, right)) -} +some_function2!(array_except [T: Eq + Clone + Hash + Ord + Debug], Array, Array, Array); #[doc(hidden)] pub fn array_union__(left: Array, right: Array) -> Array @@ -842,33 +752,7 @@ where result.into() } -#[doc(hidden)] -pub fn array_unionN_(left: Option>, right: Array) -> Option> -where - T: Eq + Clone + Hash + Ord, -{ - let left = left?; - Some(array_union__(left, right)) -} - -#[doc(hidden)] -pub fn array_union_N(left: Array, right: Option>) -> Option> -where - T: Eq + Clone + Hash + Ord, -{ - let right = right?; - Some(array_union__(left, right)) -} - -#[doc(hidden)] -pub fn array_unionNN(left: Option>, right: Option>) -> Option> -where - T: Eq + Clone + Hash + Ord, -{ - let left = left?; - let right = right?; - Some(array_union__(left, right)) -} +some_function2!(array_union [T: Eq + Clone + Hash + Ord], Array, Array, Array); #[doc(hidden)] pub fn array_intersect__(left: Array, right: Array) -> Array @@ -883,33 +767,7 @@ where result.into() } -#[doc(hidden)] -pub fn array_intersectN_(left: Option>, right: Array) -> Option> -where - T: Eq + Clone + Hash + Ord, -{ - let left = left?; - Some(array_intersect__(left, right)) -} - -#[doc(hidden)] -pub fn array_intersect_N(left: Array, right: Option>) -> Option> -where - T: Eq + Clone + Hash + Ord, -{ - let right = right?; - Some(array_intersect__(left, right)) -} - -#[doc(hidden)] -pub fn array_intersectNN(left: Option>, right: Option>) -> Option> -where - T: Eq + Clone + Hash + Ord, -{ - let left = left?; - let right = right?; - Some(array_intersect__(left, right)) -} +some_function2!(array_intersect [T: Eq + Clone + Hash + Ord], Array, Array, Array); // There are only 8 variants of array_insert, since the // compiler enforces the element type is always nullable. diff --git a/crates/sqllib/src/decimal.rs b/crates/sqllib/src/decimal.rs index d26e1d4274..1ab5082ca1 100644 --- a/crates/sqllib/src/decimal.rs +++ b/crates/sqllib/src/decimal.rs @@ -1,6 +1,8 @@ //! Operations on Decimal values -use crate::{some_polymorphic_function1, some_polymorphic_function2}; +use crate::{ + some_polymorphic_function1, some_polymorphic_function2, some_polymorphic_null_function2, +}; pub use feldera_fxp::DynamicDecimal; use feldera_fxp::Fixed; @@ -21,60 +23,7 @@ pub fn plus_SqlDecimal_SqlDecimal< left.checked_add_generic::(right).unwrap() } -#[doc(hidden)] -pub fn plus_SqlDecimalN_SqlDecimal< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: SqlDecimal, -) -> Option> { - let left = left?; - Some(plus_SqlDecimal_SqlDecimal::( - left, right, - )) -} - -#[doc(hidden)] -pub fn plus_SqlDecimal_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: SqlDecimal, - right: Option>, -) -> Option> { - let right = right?; - Some(plus_SqlDecimal_SqlDecimal::( - left, right, - )) -} - -#[doc(hidden)] -pub fn plus_SqlDecimalN_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: Option>, -) -> Option> { - let left = left?; - let right = right?; - Some(plus_SqlDecimal_SqlDecimal::( - left, right, - )) -} +some_polymorphic_function2!(plus [const P0: usize, const S0: usize, const P1: usize, const S1: usize, const P2: usize, const S2: usize], SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn minus_SqlDecimal_SqlDecimal< @@ -91,60 +40,7 @@ pub fn minus_SqlDecimal_SqlDecimal< left.checked_sub_generic::(right).unwrap() } -#[doc(hidden)] -pub fn minus_SqlDecimalN_SqlDecimal< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: SqlDecimal, -) -> Option> { - let left = left?; - Some(minus_SqlDecimal_SqlDecimal::( - left, right, - )) -} - -#[doc(hidden)] -pub fn minus_SqlDecimal_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: SqlDecimal, - right: Option>, -) -> Option> { - let right = right?; - Some(minus_SqlDecimal_SqlDecimal::( - left, right, - )) -} - -#[doc(hidden)] -pub fn minus_SqlDecimalN_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: Option>, -) -> Option> { - let left = left?; - let right = right?; - Some(minus_SqlDecimal_SqlDecimal::( - left, right, - )) -} +some_polymorphic_function2!(minus [const P0: usize, const S0: usize, const P1: usize, const S1: usize, const P2: usize, const S2: usize], SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn times_SqlDecimal_SqlDecimal< @@ -167,60 +63,7 @@ pub fn times_SqlDecimal_SqlDecimal< }) } -#[doc(hidden)] -pub fn times_SqlDecimalN_SqlDecimal< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: SqlDecimal, -) -> Option> { - let left = left?; - Some(times_SqlDecimal_SqlDecimal::( - left, right, - )) -} - -#[doc(hidden)] -pub fn times_SqlDecimal_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: SqlDecimal, - right: Option>, -) -> Option> { - let right = right?; - Some(times_SqlDecimal_SqlDecimal::( - left, right, - )) -} - -#[doc(hidden)] -pub fn times_SqlDecimalN_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: Option>, -) -> Option> { - let left = left?; - let right = right?; - Some(times_SqlDecimal_SqlDecimal::( - left, right, - )) -} +some_polymorphic_function2!(times [const P0: usize, const S0: usize, const P1: usize, const S1: usize, const P2: usize, const S2: usize], SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn div_SqlDecimal_SqlDecimal< @@ -238,60 +81,7 @@ pub fn div_SqlDecimal_SqlDecimal< .unwrap_or_else(|| panic!("Attempt to divide by zero: {}/{}", left, right)) } -#[doc(hidden)] -pub fn div_SqlDecimalN_SqlDecimal< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: SqlDecimal, -) -> Option> { - let left = left?; - Some(div_SqlDecimal_SqlDecimal::( - left, right, - )) -} - -#[doc(hidden)] -pub fn div_SqlDecimal_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: SqlDecimal, - right: Option>, -) -> Option> { - let right = right?; - Some(div_SqlDecimal_SqlDecimal::( - left, right, - )) -} - -#[doc(hidden)] -pub fn div_SqlDecimalN_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: Option>, -) -> Option> { - let left = left?; - let right = right?; - Some(div_SqlDecimal_SqlDecimal::( - left, right, - )) -} +some_polymorphic_function2!(div [const P0: usize, const S0: usize, const P1: usize, const S1: usize, const P2: usize, const S2: usize], SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn div_null_SqlDecimal_SqlDecimal< @@ -308,54 +98,7 @@ pub fn div_null_SqlDecimal_SqlDecimal< left.checked_div_generic::(right) } -#[doc(hidden)] -pub fn div_null_SqlDecimalN_SqlDecimal< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: SqlDecimal, -) -> Option> { - let left = left?; - div_null_SqlDecimal_SqlDecimal::(left, right) -} - -#[doc(hidden)] -pub fn div_null_SqlDecimal_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: SqlDecimal, - right: Option>, -) -> Option> { - let right = right?; - div_null_SqlDecimal_SqlDecimal::(left, right) -} - -#[doc(hidden)] -pub fn div_null_SqlDecimalN_SqlDecimalN< - const P0: usize, - const S0: usize, - const P1: usize, - const S1: usize, - const P2: usize, - const S2: usize, ->( - left: Option>, - right: Option>, -) -> Option> { - let left = left?; - let right = right?; - div_null_SqlDecimal_SqlDecimal::(left, right) -} +some_polymorphic_null_function2!(div_null [const P0: usize, const S0: usize, const P1: usize, const S1: usize, const P2: usize, const S2: usize], SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn modulo_SqlDecimal_SqlDecimal< @@ -434,7 +177,7 @@ pub fn abs_SqlDecimal(left: SqlDecimal) -> left.abs() } -some_polymorphic_function1!(abs, SqlDecimal, SqlDecimal, SqlDecimal); +some_polymorphic_function1!(abs [const P: usize, const S: usize], SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn floor_SqlDecimal( @@ -443,7 +186,7 @@ pub fn floor_SqlDecimal( value.int_floor() } -some_polymorphic_function1!(floor, SqlDecimal, SqlDecimal, SqlDecimal); +some_polymorphic_function1!(floor [const P: usize, const S: usize], SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn ceil_SqlDecimal( @@ -452,7 +195,7 @@ pub fn ceil_SqlDecimal( value.int_ceil() } -some_polymorphic_function1!(ceil, SqlDecimal, SqlDecimal, SqlDecimal); +some_polymorphic_function1!(ceil [const P: usize, const S: usize], SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn trunc_SqlDecimal( @@ -462,7 +205,7 @@ pub fn trunc_SqlDecimal( SqlDecimal::new(trunc.internal_representation(), 0).unwrap() } -some_polymorphic_function1!(trunc, SqlDecimal, SqlDecimal, SqlDecimal); +some_polymorphic_function1!(trunc [const P: usize, const S: usize], SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn round_SqlDecimal( @@ -471,7 +214,7 @@ pub fn round_SqlDecimal( value.convert_round_even::().unwrap() } -some_polymorphic_function1!(round, SqlDecimal, SqlDecimal, SqlDecimal); +some_polymorphic_function1!(round [const P: usize, const S: usize], SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn round_SqlDecimal_i32( @@ -481,7 +224,7 @@ pub fn round_SqlDecimal_i32( value.round(digits) } -some_polymorphic_function2!(round, SqlDecimal, SqlDecimal, i32, i32, SqlDecimal); +some_polymorphic_function2!(round [const P: usize, const S: usize], SqlDecimal, SqlDecimal, i32, i32, SqlDecimal); #[doc(hidden)] pub fn bround_SqlDecimal_i32( @@ -491,7 +234,7 @@ pub fn bround_SqlDecimal_i32( value.round_ties_even(digits) } -some_polymorphic_function2!(bround, SqlDecimal, SqlDecimal, i32, i32, SqlDecimal); +some_polymorphic_function2!(bround [const P: usize, const S: usize], SqlDecimal, SqlDecimal, i32, i32, SqlDecimal); #[doc(hidden)] pub fn truncate_SqlDecimal_i32( @@ -501,7 +244,7 @@ pub fn truncate_SqlDecimal_i32( value.trunc_digits(digits) } -some_polymorphic_function2!(truncate, SqlDecimal, SqlDecimal, i32, i32, SqlDecimal); +some_polymorphic_function2!(truncate [const P: usize, const S: usize], SqlDecimal, SqlDecimal, i32, i32, SqlDecimal); #[doc(hidden)] pub fn sign_SqlDecimal( @@ -511,7 +254,7 @@ pub fn sign_SqlDecimal( value.sign().convert().unwrap() } -some_polymorphic_function1!(sign, SqlDecimal, SqlDecimal, SqlDecimal); +some_polymorphic_function1!(sign [const P: usize, const S: usize], SqlDecimal, SqlDecimal, SqlDecimal); #[doc(hidden)] pub fn decimal_to_integer_(dec: SqlDecimal) -> i128 { diff --git a/crates/sqllib/src/float.rs b/crates/sqllib/src/float.rs index f9f0caecb4..a629c72e81 100644 --- a/crates/sqllib/src/float.rs +++ b/crates/sqllib/src/float.rs @@ -1,6 +1,6 @@ use crate::{ SqlString, finite_or_null, some_function1, some_polymorphic_function1, - some_polymorphic_function2, + some_polymorphic_function2, some_polymorphic_null_function1, }; use dbsp::algebra::{F32, F64}; use lexical_core::format::STANDARD; @@ -536,22 +536,11 @@ pub fn finite_or_null_d(value: F64) -> Option { finite_or_null(value.into_inner()).map(|x| x.into()) } -#[inline(always)] -#[doc(hidden)] -pub fn finite_or_null_dN(value: Option) -> Option { - let value = value?; - finite_or_null_d(value) -} +some_polymorphic_null_function1!(finite_or_null, d, F64, F64); -#[inline(always)] #[doc(hidden)] pub fn finite_or_null_f(value: F32) -> Option { finite_or_null(value.into_inner()).map(|x| x.into()) } -#[inline(always)] -#[doc(hidden)] -pub fn finite_or_null_fN(value: Option) -> Option { - let value = value?; - finite_or_null_f(value) -} +some_polymorphic_null_function1!(finite_or_null, f, F32, F32); diff --git a/crates/sqllib/src/interval.rs b/crates/sqllib/src/interval.rs index abc352e60c..d9dc7d857e 100644 --- a/crates/sqllib/src/interval.rs +++ b/crates/sqllib/src/interval.rs @@ -6,6 +6,7 @@ use crate::{ operators::{eq, gt, gte, lt, lte, neq}, plus_Date_Date_LongInterval__, sign, some_existing_operator, some_function1, some_function2, some_operator, some_polymorphic_function1, some_polymorphic_function2, + some_polymorphic_null_function2, timestamp::{extract_epoch_Date, extract_quarter_Date}, }; use dbsp::{algebra::F64, num_entries_scalar}; @@ -411,7 +412,7 @@ pub fn div_ShortInterval_SqlDecimal( } some_polymorphic_function2!( - div , + div [const P: usize, const S: usize], ShortInterval, ShortInterval, SqlDecimal, @@ -430,33 +431,7 @@ pub fn div_null_ShortInterval_SqlDecimal( Some(ShortInterval::from_microseconds(micros)) } -#[doc(hidden)] -pub fn div_null_ShortIntervalN_SqlDecimal( - left: Option, - right: SqlDecimal, -) -> Option { - let left = left?; - div_null_ShortInterval_SqlDecimal(left, right) -} - -#[doc(hidden)] -pub fn div_null_ShortInterval_SqlDecimalN( - left: ShortInterval, - right: Option>, -) -> Option { - let right = right?; - div_null_ShortInterval_SqlDecimal(left, right) -} - -#[doc(hidden)] -pub fn div_null_ShortIntervalN_SqlDecimalN( - left: Option, - right: Option>, -) -> Option { - let left = left?; - let right = right?; - div_null_ShortInterval_SqlDecimal(left, right) -} +some_polymorphic_null_function2!(div_null [const P: usize, const S: usize], ShortInterval, ShortInterval, SqlDecimal, SqlDecimal, ShortInterval); #[doc(hidden)] pub fn times_ShortInterval_i64(left: ShortInterval, right: i64) -> ShortInterval { @@ -481,7 +456,7 @@ pub fn times_ShortInterval_SqlDecimal( } some_polymorphic_function2!( - times , + times [const P: usize, const S: usize], ShortInterval, ShortInterval, SqlDecimal, @@ -506,27 +481,14 @@ pub fn div_null_ShortInterval_d(left: ShortInterval, right: F64) -> Option, right: F64) -> Option { - let left = left?; - div_null_ShortInterval_d(left, right) -} - -#[doc(hidden)] -pub fn div_null_ShortInterval_dN(left: ShortInterval, right: Option) -> Option { - let right = right?; - div_null_ShortInterval_d(left, right) -} - -#[doc(hidden)] -pub fn div_null_ShortIntervalN_dN( - left: Option, - right: Option, -) -> Option { - let left = left?; - let right = right?; - div_null_ShortInterval_d(left, right) -} +some_polymorphic_null_function2!( + div_null, + ShortInterval, + ShortInterval, + d, + F64, + ShortInterval +); #[doc(hidden)] pub fn div_ShortInterval_i64(left: ShortInterval, right: i64) -> ShortInterval { @@ -542,33 +504,14 @@ pub fn div_null_ShortInterval_i64(left: ShortInterval, right: i64) -> Option, - right: i64, -) -> Option { - let left = left?; - div_null_ShortInterval_i64(left, right) -} - -#[doc(hidden)] -pub fn div_null_ShortInterval_i64N( - left: ShortInterval, - right: Option, -) -> Option { - let right = right?; - div_null_ShortInterval_i64(left, right) -} - -#[doc(hidden)] -pub fn div_null_ShortIntervalN_i64N( - left: Option, - right: Option, -) -> Option { - let left = left?; - let right = right?; - div_null_ShortInterval_i64(left, right) -} +some_polymorphic_null_function2!( + div_null, + ShortInterval, + ShortInterval, + i64, + i64, + ShortInterval +); #[doc(hidden)] pub fn plus_ShortInterval_ShortInterval_ShortInterval__( @@ -879,7 +822,7 @@ pub fn times_LongInterval_SqlDecimal( } some_polymorphic_function2!( - times , + times [const P: usize, const S: usize], LongInterval, LongInterval, SqlDecimal, @@ -901,27 +844,7 @@ pub fn div_null_LongInterval_i32(left: LongInterval, right: i32) -> Option, right: i32) -> Option { - let left = left?; - div_null_LongInterval_i32(left, right) -} - -#[doc(hidden)] -pub fn div_null_LongInterval_i32N(left: LongInterval, right: Option) -> Option { - let right = right?; - div_null_LongInterval_i32(left, right) -} - -#[doc(hidden)] -pub fn div_null_LongIntervalN_i32N( - left: Option, - right: Option, -) -> Option { - let left = left?; - let right = right?; - div_null_LongInterval_i32(left, right) -} +some_polymorphic_null_function2!(div_null, LongInterval, LongInterval, i32, i32, LongInterval); #[doc(hidden)] pub fn div_LongInterval_d(left: LongInterval, right: F64) -> LongInterval { @@ -940,27 +863,7 @@ pub fn div_null_LongInterval_d(left: LongInterval, right: F64) -> Option, right: F64) -> Option { - let left = left?; - div_null_LongInterval_d(left, right) -} - -#[doc(hidden)] -pub fn div_null_LongInterval_dN(left: LongInterval, right: Option) -> Option { - let right = right?; - div_null_LongInterval_d(left, right) -} - -#[doc(hidden)] -pub fn div_null_LongIntervalN_dN( - left: Option, - right: Option, -) -> Option { - let left = left?; - let right = right?; - div_null_LongInterval_d(left, right) -} +some_polymorphic_null_function2!(div_null, LongInterval, LongInterval, d, F64, LongInterval); #[doc(hidden)] pub fn div_LongInterval_SqlDecimal( @@ -971,7 +874,7 @@ pub fn div_LongInterval_SqlDecimal( } some_polymorphic_function2!( - div , + div [const P: usize, const S: usize], LongInterval, LongInterval, SqlDecimal, @@ -990,33 +893,7 @@ pub fn div_null_LongInterval_SqlDecimal( Some(LongInterval::from_months(months)) } -#[doc(hidden)] -pub fn div_null_LongIntervalN_SqlDecimal( - left: Option, - right: SqlDecimal, -) -> Option { - let left = left?; - div_null_LongInterval_SqlDecimal(left, right) -} - -#[doc(hidden)] -pub fn div_null_LongInterval_SqlDecimalN( - left: LongInterval, - right: Option>, -) -> Option { - let right = right?; - div_null_LongInterval_SqlDecimal(left, right) -} - -#[doc(hidden)] -pub fn div_null_LongIntervalN_SqlDecimalN( - left: Option, - right: Option>, -) -> Option { - let left = left?; - let right = right?; - div_null_LongInterval_SqlDecimal(left, right) -} +some_polymorphic_null_function2!(div_null [const P: usize, const S: usize], LongInterval, LongInterval, SqlDecimal, SqlDecimal, LongInterval); #[doc(hidden)] pub fn plus_LongInterval_LongInterval_LongInterval__( diff --git a/crates/sqllib/src/lib.rs b/crates/sqllib/src/lib.rs index 24885b7859..c87c60ba40 100644 --- a/crates/sqllib/src/lib.rs +++ b/crates/sqllib/src/lib.rs @@ -233,483 +233,495 @@ pub type WSet = OrdZSet; #[doc(hidden)] pub type IndexedWSet = OrdIndexedZSet; -/// Macro to create variants of a function with 1 argument -/// If there exists a function is f_(x: T) -> S, this creates a function -/// fN(x: Option) -> Option, defined as -/// fN(x) { let x = x?; Some(f_(x)) }. -macro_rules! some_function1 { - ($func_name:ident, $arg_type:ty, $ret_type:ty) => { - ::paste::paste! { - #[doc(hidden)] - pub fn [<$func_name N>]( arg: Option<$arg_type> ) -> Option<$ret_type> { - let arg = arg?; - Some([<$func_name _>](arg)) - } - } +/// Internal base used by [`some_function1`]–[`some_function4`]. +/// +/// Given a base function `f` with *N* non-optional arguments and return type +/// `R`, generates all 2^N − 1 nullable-wrapper variants: one for each +/// non-empty subset of arguments that may be `Option`. The +/// all-non-nullable combination is skipped because that is the base function. +/// +/// Each argument type is passed wrapped in parentheses (e.g. `(i32)`) so that +/// generic types like `Array` survive token-tree accumulation as a single +/// `tt`; Rust treats `(T)` as a type identical to `T` in all positions. +/// +/// State carried through `@step`: +/// - `[$($tgen:tt)*]` — type-generic declarations, e.g. `T: Clone, U: Eq`; empty when absent +/// - `[$(($dd, $dt, $dn)),*]` — decided args: `(suffix char, paren-wrapped type, arg ident)` +/// - `[$($base)*]` — base suffix: one `_` per arg, used to name the base function +/// - `$wrap` — `y` to wrap the base call in `Some(…)`, `n` to return directly +/// - `$has_n` — `y` once any nullable branch is taken, `n` otherwise +/// - `[$(($an, $at)),*]` — remaining args: `(arg ident, paren-wrapped type)` +#[doc(hidden)] +#[macro_export] +macro_rules! some_function_impl { + // ── helpers ──────────────────────────────────────────────────────────── + // Produce the parameter type: `_` → bare type, `N` → Option-wrapped type. + // The argument is always a paren-wrapped type `($t)`; the pattern `($t:ty)` + // strips the outer parens so the emitted type is `T`, not `(T)`. + (@type _ ($t:ty)) => { $t }; + (@type N ($t:ty)) => { Option<$t> }; + + // Produce the unwrap statement: `_` → nothing, `N` → `let x = x?;` + (@unwrap _ $n:ident) => {}; + (@unwrap N $n:ident) => { let $n = $n?; }; + + // ── combination generator ─────────────────────────────────────────────── + // Recursive step: branch into non-nullable (`_`) and nullable (`N`). + // `$tgen` is threaded through unchanged. + (@step $fn:ident, $ret:ty, [$($tgen:tt)*], + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($base:tt)*]; $wrap:tt; $has_n:tt; + [($an:ident, $at:tt) $(, ($rn:ident, $rt:tt))*] + ) => { + $crate::some_function_impl!(@step $fn, $ret, [$($tgen)*], + [$(($dd, $dt, $dn),)* (_, $at, $an)], [$($base)* _]; $wrap; $has_n; + [$(($rn, $rt)),*] + ); + $crate::some_function_impl!(@step $fn, $ret, [$($tgen)*], + [$(($dd, $dt, $dn),)* (N, $at, $an)], [$($base)* _]; $wrap; y; + [$(($rn, $rt)),*] + ); }; -} -pub(crate) use some_function1; + // Base: all non-nullable — skip (would duplicate the base function itself). + (@step $fn:ident, $ret:ty, [$($tgen:tt)*], + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($base:tt)*]; $wrap:tt; n; [] + ) => {}; -/// Macro to create variants of a function with 1 argument -/// If there exists a function is f_type(x: T) -> S, this creates a function -/// f_typeN(x: Option) -> Option -/// { let x = x?; Some(f_type(x)) }. -macro_rules! some_polymorphic_function1 { - ($func_name:ident $(< $( const $var : ident : $ty: ty),* >)?, $type_name: ident, $arg_type:ty, $ret_type:ty) => { + // Base: ≥1 nullable, no type generics, wrap in Some(). + (@step $fn:ident, $ret:ty, [], + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($base:tt)*]; y; y; [] + ) => { ::paste::paste! { #[doc(hidden)] - pub fn [<$func_name _ $type_name N>] $(< $( const $var : $ty ),* >)? ( arg: Option<$arg_type> ) -> Option<$ret_type> { - let arg = arg?; - Some([<$func_name _ $type_name >] $(:: < $($var),* >)? (arg)) + pub fn [<$fn $($dd)*>]( + $( $dn: $crate::some_function_impl!(@type $dd $dt) ),* + ) -> Option<$ret> { + $( $crate::some_function_impl!(@unwrap $dd $dn); )* + Some([<$fn $($base)*>]($($dn),*)) } } }; -} - -pub(crate) use some_polymorphic_function1; -/// Macro to create variants of a function with 2 arguments -/// If there exists a function is f__(x: T, y: S) -> U, this creates -/// three functions: -/// - f_N(x: T, y: Option) -> Option -/// - fN_(x: Option, y: S) -> Option -/// - fNN(x: Option, y: Option) -> Option -/// -/// The resulting functions return Some only if all arguments are 'Some'. -macro_rules! some_function2 { - ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $ret_type:ty) => { + // Base: ≥1 nullable, type generics present, wrap in Some(). + (@step $fn:ident, $ret:ty, [$($tgen:tt)+], + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($base:tt)*]; y; y; [] + ) => { ::paste::paste! { #[doc(hidden)] - pub fn [<$func_name NN>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1> ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - Some([<$func_name __>](arg0, arg1)) - } - - #[doc(hidden)] - pub fn [<$func_name _N>]( arg0: $arg_type0, arg1: Option<$arg_type1> ) -> Option<$ret_type> { - let arg1 = arg1?; - Some([<$func_name __>](arg0, arg1)) - } - - #[doc(hidden)] - pub fn [<$func_name N_>]( arg0: Option<$arg_type0>, arg1: $arg_type1 ) -> Option<$ret_type> { - let arg0 = arg0?; - Some([<$func_name __>](arg0, arg1)) + pub fn [<$fn $($dd)*>]< $($tgen)* >( + $( $dn: $crate::some_function_impl!(@type $dd $dt) ),* + ) -> Option<$ret> { + $( $crate::some_function_impl!(@unwrap $dd $dn); )* + Some([<$fn $($base)*>]($($dn),*)) } } - } -} - -pub(crate) use some_function2; + }; -/// Macro to create variants of a polymorphic function with 2 arguments -/// If there exists a function is f_type1_type2(x: T, y: S) -> U, this -/// creates three functions: -/// - f_type1_type2N(x: T, y: Option) -> Option -/// - f_type1N_type2(x: Option, y: S) -> Option -/// - f_type1N_type2N(x: Option, y: Option) -> Option -/// -/// The resulting functions return Some only if all arguments are 'Some'. -macro_rules! some_polymorphic_function2 { - ($func_name:ident $(< $( const $var:ident : $ty: ty),* >)?, $type_name0: ident, $arg_type0:ty, $type_name1: ident, $arg_type1:ty, $ret_type:ty) => { + // Base: ≥1 nullable, no type generics, direct return. + (@step $fn:ident, $ret:ty, [], + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($base:tt)*]; n; y; [] + ) => { ::paste::paste! { #[doc(hidden)] - pub fn [<$func_name _$type_name0 _ $type_name1 N>] $(< $( const $var : $ty),* >)? ( arg0: $arg_type0, arg1: Option<$arg_type1> ) -> Option<$ret_type> { - let arg1 = arg1?; - Some([<$func_name _ $type_name0 _ $type_name1>] $(:: < $($var),* >)? (arg0, arg1)) + pub fn [<$fn $($dd)*>]( + $( $dn: $crate::some_function_impl!(@type $dd $dt) ),* + ) -> Option<$ret> { + $( $crate::some_function_impl!(@unwrap $dd $dn); )* + [<$fn $($base)*>]($($dn),*) } + } + }; + // Base: ≥1 nullable, type generics present, direct return. + (@step $fn:ident, $ret:ty, [$($tgen:tt)+], + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($base:tt)*]; n; y; [] + ) => { + ::paste::paste! { #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1>] $(< $( const $var : $ty),* >)? ( arg0: Option<$arg_type0>, arg1: $arg_type1 ) -> Option<$ret_type> { - let arg0 = arg0?; - Some([<$func_name _ $type_name0 _ $type_name1>] $(:: < $($var),* >)? (arg0, arg1)) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 N>] $(< $( const $var : $ty),* >)? ( arg0: Option<$arg_type0>, arg1: Option<$arg_type1> ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - Some([<$func_name _ $type_name0 _ $type_name1>] $(:: < $($var),* >)? (arg0, arg1)) + pub fn [<$fn $($dd)*>]< $($tgen)* >( + $( $dn: $crate::some_function_impl!(@type $dd $dt) ),* + ) -> Option<$ret> { + $( $crate::some_function_impl!(@unwrap $dd $dn); )* + [<$fn $($base)*>]($($dn),*) } } - } + }; } -pub(crate) use some_polymorphic_function2; - -/// If there exists a function is f_t1_t2_t3(x: T, y: S, z: V) -> U, this creates -/// seven functions: -/// - f_t1_t2_t3N(x: T, y: S, z: Option) -> Option -/// - f_t1_t2N_t2(x: T, y: Option, z: V) -> Option -/// - etc. +/// Macro to create variants of a function with 1 argument. +/// If there exists a function `f_(x: T) -> S`, this creates: +/// - `fN(x: Option) -> Option` /// -/// The resulting functions return Some only if all arguments are 'Some'. -macro_rules! some_polymorphic_function3 { - ($func_name:ident, - $type_name0: ident, $arg_type0:ty, - $type_name1: ident, $arg_type1:ty, - $type_name2: ident, $arg_type2: ty, - $ret_type:ty) => { - ::paste::paste! { - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 _ $type_name1 _ $type_name2 N>]( - arg0: $arg_type0, - arg1: $arg_type1, - arg2: Option<$arg_type2> - ) -> Option<$ret_type> { - let arg2 = arg2?; - Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 _ $type_name1 N _ $type_name2>]( - arg0: $arg_type0, - arg1: Option<$arg_type1>, - arg2: $arg_type2 - ) -> Option<$ret_type> { - let arg1 = arg1?; - Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 _ $type_name1 N _ $type_name2 N>]( - arg0: $arg_type0, - arg1: Option<$arg_type1>, - arg2: Option<$arg_type2> - ) -> Option<$ret_type> { - let arg1 = arg1?; - let arg2 = arg2?; - Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 _ $type_name2>]( - arg0: Option<$arg_type0>, - arg1: $arg_type1, - arg2: $arg_type2 - ) -> Option<$ret_type> { - let arg0 = arg0?; - Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 _ $type_name2 N>]( - arg0: Option<$arg_type0>, - arg1: $arg_type1, - arg2: Option<$arg_type2> - ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg2 = arg2?; - Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 N _ $type_name2>]( - arg0: Option<$arg_type0>, - arg1: Option<$arg_type1>, - arg2: $arg_type2 - ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 N _ $type_name2 N>]( - arg0: Option<$arg_type0>, - arg1: Option<$arg_type1>, - arg2: Option<$arg_type2> - ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - let arg2 = arg2?; - Some([<$func_name _ $type_name0 _ $type_name1 _ $type_name2>](arg0, arg1, arg2)) - } - } +/// The generated function returns `None` when any argument is `None`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_function1 { + ($func_name:ident, $arg_type:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [], [], []; y; n; + [(arg0, ($arg_type))] + ); + }; + ($func_name:ident [$($tgen:tt)*], $arg_type:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [$($tgen)*], [], []; y; n; + [(arg0, ($arg_type))] + ); }; } -pub(crate) use some_polymorphic_function3; +/// Internal base used by [`some_polymorphic_function1`]–[`some_polymorphic_function3`] +/// and [`some_polymorphic_null_function3`]. +/// +/// Generates all 2^N − 1 nullable-wrapper variants of a polymorphic function whose +/// name includes SQL type names (e.g. `f_t0N_t1_t2`). +/// +/// State carried through `@step`: +/// - `[$($cdecl:tt)*]`, `[$($cinvoke:tt)*]` — const-generic declaration and invocation +/// tokens (e.g. `const P: usize, const S: usize` and `P, S`), or `[]`/`[]` when absent. +/// - `$wrap` — `y` to wrap the base call in `Some(…)`, `n` to return it directly. +/// - `[$(($dd, $dt, $dn)),*]` — decided args: `(suffix char, paren type, arg ident)`. +/// - `[$($sfx)*]`, `[$($bsfx)*]` — variant name suffix and base name suffix token lists. +/// - `$has_n` — `y` once any nullable branch is taken. +/// - `[$(($an, $atn, $at)),*]` — remaining args: `(arg ident, type name ident, paren type)`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_polymorphic_function_impl { + // ── Recursive step ───────────────────────────────────────────────────── + // Branch into non-nullable (`_`) and nullable (`N`) for the next argument. + // The type name is embedded directly into the accumulated suffix tokens. + (@step $fn:ident, $ret:ty, + [$($cdecl:tt)*], [$($cinvoke:tt)*]; $wrap:tt; + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($sfx:tt)*], [$($bsfx:tt)*]; $has_n:tt; + [($an:ident, $atn:ident, $at:tt) $(, ($rn:ident, $rtn:ident, $rt:tt))*] + ) => { + $crate::some_polymorphic_function_impl!(@step $fn, $ret, + [$($cdecl)*], [$($cinvoke)*]; $wrap; + [$(($dd, $dt, $dn),)* (_, $at, $an)], [$($sfx)* _ $atn], [$($bsfx)* _ $atn]; $has_n; + [$(($rn, $rtn, $rt)),*] + ); + $crate::some_polymorphic_function_impl!(@step $fn, $ret, + [$($cdecl)*], [$($cinvoke)*]; $wrap; + [$(($dd, $dt, $dn),)* (N, $at, $an)], [$($sfx)* _ $atn N], [$($bsfx)* _ $atn]; y; + [$(($rn, $rtn, $rt)),*] + ); + }; -/// If there exists a function is f_t1_t2_t3(x: T, y: S, z: V) -> Option, this creates -/// seven functions: -/// - f_t1_t2_t3N(x: T, y: S, z: Option) -> Option -/// - f_t1_t2N_t2(x: T, y: Option, z: V) -> Option -/// - etc. -// This is like some_polymorphic_function3, but the result is always Option. -macro_rules! some_polymorphic_null_function3 { - ($func_name:ident $(< $( const $var : ident : $ty: ty),* >)?, - $type_name0: ident, $arg_type0:ty, - $type_name1: ident, $arg_type1:ty, - $type_name2: ident, $arg_type2: ty, - $ret_type:ty) => { + // ── Base: all non-nullable — skip ────────────────────────────────────── + (@step $fn:ident, $ret:ty, + [$($cdecl:tt)*], [$($cinvoke:tt)*]; $wrap:tt; + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($sfx:tt)*], [$($bsfx:tt)*]; n; [] + ) => {}; + + // ── Base: ≥1 nullable, no const generics, wrap in Some() ────────────── + (@step $fn:ident, $ret:ty, + [], []; y; + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($sfx:tt)*], [$($bsfx:tt)*]; y; [] + ) => { ::paste::paste! { #[doc(hidden)] - pub fn [<$func_name _ $type_name0 _ $type_name1 _ $type_name2 N>] $(< $( const $var : $ty ),* >)? ( - arg0: $arg_type0, - arg1: $arg_type1, - arg2: Option<$arg_type2> - ) -> Option<$ret_type> { - let arg2 = arg2?; - [<$func_name _ $type_name0 _ $type_name1 _ $type_name2>] $(:: < $($var),* >)? (arg0, arg1, arg2) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 _ $type_name1 N _ $type_name2>] $(< $( const $var : $ty ),* >)? ( - arg0: $arg_type0, - arg1: Option<$arg_type1>, - arg2: $arg_type2 - ) -> Option<$ret_type> { - let arg1 = arg1?; - [<$func_name _ $type_name0 _ $type_name1 _ $type_name2>] $(:: < $($var),* >)? (arg0, arg1, arg2) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 _ $type_name1 N _ $type_name2 N>] $(< $( const $var : $ty ),* >)? ( - arg0: $arg_type0, - arg1: Option<$arg_type1>, - arg2: Option<$arg_type2> - ) -> Option<$ret_type> { - let arg1 = arg1?; - let arg2 = arg2?; - [<$func_name _ $type_name0 _ $type_name1 _ $type_name2>] $(:: < $($var),* >)? (arg0, arg1, arg2) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 _ $type_name2>] $(< $( const $var : $ty ),* >)? ( - arg0: Option<$arg_type0>, - arg1: $arg_type1, - arg2: $arg_type2 - ) -> Option<$ret_type> { - let arg0 = arg0?; - [<$func_name _ $type_name0 _ $type_name1 _ $type_name2>] $(:: < $($var),* >)? (arg0, arg1, arg2) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 _ $type_name2 N>] $(< $( const $var : $ty ),* >)? ( - arg0: Option<$arg_type0>, - arg1: $arg_type1, - arg2: Option<$arg_type2> - ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg2 = arg2?; - [<$func_name _ $type_name0 _ $type_name1 _ $type_name2>] $(:: < $($var),* >)? (arg0, arg1, arg2) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 N _ $type_name2>] $(< $( const $var : $ty ),* >)? ( - arg0: Option<$arg_type0>, - arg1: Option<$arg_type1>, - arg2: $arg_type2 - ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - [<$func_name _ $type_name0 _ $type_name1 _ $type_name2>] $(:: < $($var),* >)? (arg0, arg1, arg2) - } - - #[doc(hidden)] - pub fn [<$func_name _ $type_name0 N _ $type_name1 N _ $type_name2 N>] $(< $( const $var : $ty ),* >)? ( - arg0: Option<$arg_type0>, - arg1: Option<$arg_type1>, - arg2: Option<$arg_type2> - ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - let arg2 = arg2?; - [<$func_name _ $type_name0 _ $type_name1 _ $type_name2>] $(:: < $($var),* >)? (arg0, arg1, arg2) + pub fn [<$fn $($sfx)*>]( + $( $dn: $crate::some_function_impl!(@type $dd $dt) ),* + ) -> Option<$ret> { + $( $crate::some_function_impl!(@unwrap $dd $dn); )* + Some([<$fn $($bsfx)*>]($($dn),*)) } } }; -} - -pub(crate) use some_polymorphic_null_function3; -/// If there exists a function is f___(x: T, y: S, z: V) -> U, this creates -/// seven functions: -/// - f__N(x: T, y: S, z: Option) -> Option -/// - f_N_(x: T, y: Option, z: V) -> Option -/// - etc. -/// -/// The resulting functions return Some only if all arguments are 'Some'. -macro_rules! some_function3 { - ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $arg_type2: ty, $ret_type:ty) => { + // ── Base: ≥1 nullable, const generics present, wrap in Some() ───────── + (@step $fn:ident, $ret:ty, + [$($cdecl:tt)+], [$($cinvoke:tt)+]; y; + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($sfx:tt)*], [$($bsfx:tt)*]; y; [] + ) => { ::paste::paste! { #[doc(hidden)] - pub fn [<$func_name __N>]( arg0: $arg_type0, arg1: $arg_type1, arg2: Option<$arg_type2> ) -> Option<$ret_type> { - let arg2 = arg2?; - Some([<$func_name ___>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name _N_>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: $arg_type2 ) -> Option<$ret_type> { - let arg1 = arg1?; - Some([<$func_name ___>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name _NN>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: Option<$arg_type2> ) -> Option<$ret_type> { - let arg1 = arg1?; - let arg2 = arg2?; - Some([<$func_name ___>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name N__>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: $arg_type2 ) -> Option<$ret_type> { - let arg0 = arg0?; - Some([<$func_name ___>](arg0, arg1, arg2)) - } - - #[doc(hidden)] - pub fn [<$func_name N_N>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: Option<$arg_type2> ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg2 = arg2?; - Some([<$func_name ___>](arg0, arg1, arg2)) + pub fn [<$fn $($sfx)*>]< $($cdecl)* >( + $( $dn: $crate::some_function_impl!(@type $dd $dt) ),* + ) -> Option<$ret> { + $( $crate::some_function_impl!(@unwrap $dd $dn); )* + Some([<$fn $($bsfx)*>]::< $($cinvoke)* >($($dn),*)) } + } + }; + // ── Base: ≥1 nullable, no const generics, direct return ─────────────── + (@step $fn:ident, $ret:ty, + [], []; n; + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($sfx:tt)*], [$($bsfx:tt)*]; y; [] + ) => { + ::paste::paste! { #[doc(hidden)] - pub fn [<$func_name NN_>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: $arg_type2 ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - Some([<$func_name ___>](arg0, arg1, arg2)) + pub fn [<$fn $($sfx)*>]( + $( $dn: $crate::some_function_impl!(@type $dd $dt) ),* + ) -> Option<$ret> { + $( $crate::some_function_impl!(@unwrap $dd $dn); )* + [<$fn $($bsfx)*>]($($dn),*) } + } + }; + // ── Base: ≥1 nullable, const generics present, direct return ────────── + (@step $fn:ident, $ret:ty, + [$($cdecl:tt)+], [$($cinvoke:tt)+]; n; + [$(($dd:tt, $dt:tt, $dn:ident)),*], [$($sfx:tt)*], [$($bsfx:tt)*]; y; [] + ) => { + ::paste::paste! { #[doc(hidden)] - pub fn [<$func_name NNN>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: Option<$arg_type2> ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - let arg2 = arg2?; - Some([<$func_name ___>](arg0, arg1, arg2)) + pub fn [<$fn $($sfx)*>]< $($cdecl)* >( + $( $dn: $crate::some_function_impl!(@type $dd $dt) ),* + ) -> Option<$ret> { + $( $crate::some_function_impl!(@unwrap $dd $dn); )* + [<$fn $($bsfx)*>]::< $($cinvoke)* >($($dn),*) } } - } + }; } -pub(crate) use some_function3; +/// If there exists `f_t(x: T) -> S`, creates `f_tN(x: Option) -> Option`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_polymorphic_function1 { + ($func_name:ident, $type_name:ident, $arg_type:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [], []; y; + [], [], []; n; + [(arg0, $type_name, ($arg_type))] + ); + }; + ($func_name:ident [ $(const $var:ident : $vty:ty),* ], $type_name:ident, $arg_type:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [$(const $var: $vty),*], [$($var),*]; y; + [], [], []; n; + [(arg0, $type_name, ($arg_type))] + ); + }; +} -/// Macro to create variants of a function with 4 arguments -/// If there exists a function is f____(x: T, y: S, z: V, w: W) -> U, this -/// creates fifteen functions: -/// - f___N(x: T, y: S, z: V, w: Option) -> Option -/// - f__N_(x: T, y: S, z: Option, w: W) -> Option -/// - etc. +/// Macro to create variants of a function with 2 arguments. +/// If there exists a function `f__(x: T, y: S) -> U`, this creates: +/// - `f_N(x: T, y: Option) -> Option` +/// - `fN_(x: Option, y: S ) -> Option` +/// - `fNN(x: Option, y: Option) -> Option` /// -/// The resulting functions return Some only if all arguments are 'Some'. -macro_rules! some_function4 { - ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $arg_type2: ty, $arg_type3: ty, $ret_type:ty) => { - ::paste::paste! { - #[doc(hidden)] - pub fn [<$func_name ___N>]( arg0: $arg_type0, arg1: $arg_type1, arg2: $arg_type2, arg3: Option<$arg_type3> ) -> Option<$ret_type> { - let arg3 = arg3?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } - - #[doc(hidden)] - pub fn [<$func_name __N_>]( arg0: $arg_type0, arg1: $arg_type1, arg2: Option<$arg_type2>, arg3: $arg_type3 ) -> Option<$ret_type> { - let arg2 = arg2?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } - - #[doc(hidden)] - pub fn [<$func_name __NN>]( arg0: $arg_type0, arg1: $arg_type1, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> { - let arg2 = arg2?; - let arg3 = arg3?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } - - #[doc(hidden)] - pub fn [<$func_name _N__>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: $arg_type2, arg3: $arg_type3 ) -> Option<$ret_type> { - let arg1 = arg1?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } - - #[doc(hidden)] - pub fn [<$func_name _N_N>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: $arg_type2, arg3: Option<$arg_type3> ) -> Option<$ret_type> { - let arg1 = arg1?; - let arg3 = arg3?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// Each generated function returns `None` when any argument is `None`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_function2 { + ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [], [], []; y; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1))] + ); + }; + ($func_name:ident [$($tgen:tt)*], $arg_type0:ty, $arg_type1:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [$($tgen)*], [], []; y; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name _NN_>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: $arg_type3 ) -> Option<$ret_type> { - let arg1 = arg1?; - let arg2 = arg2?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// Like [`some_polymorphic_function1`], but the base function already returns +/// `Option`, so wrappers return it directly without an extra `Some()`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_polymorphic_null_function1 { + ($func_name:ident, $type_name:ident, $arg_type:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [], []; n; + [], [], []; n; + [(arg0, $type_name, ($arg_type))] + ); + }; + ($func_name:ident [ $(const $var:ident : $vty:ty),* ], $type_name:ident, $arg_type:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [$(const $var: $vty),*], [$($var),*]; n; + [], [], []; n; + [(arg0, $type_name, ($arg_type))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name _NNN>]( arg0: $arg_type0, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> { - let arg1 = arg1?; - let arg2 = arg2?; - let arg3 = arg3?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// If there exists `f_t0_t1(x: T, y: S) -> U`, creates: +/// `f_t0_t1N`, `f_t0N_t1`, `f_t0N_t1N`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_polymorphic_function2 { + ($func_name:ident, $type_name0:ident, $arg_type0:ty, $type_name1:ident, $arg_type1:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [], []; y; + [], [], []; n; + [(arg0, $type_name0, ($arg_type0)), (arg1, $type_name1, ($arg_type1))] + ); + }; + ($func_name:ident [ $(const $var:ident : $vty:ty),* ], $type_name0:ident, $arg_type0:ty, $type_name1:ident, $arg_type1:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [$(const $var: $vty),*], [$($var),*]; y; + [], [], []; n; + [(arg0, $type_name0, ($arg_type0)), (arg1, $type_name1, ($arg_type1))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name N___>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: $arg_type2, arg3: $arg_type3 ) -> Option<$ret_type> { - let arg0 = arg0?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// Like [`some_polymorphic_function2`], but the base function already returns +/// `Option`, so wrappers return it directly without an extra `Some()`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_polymorphic_null_function2 { + ($func_name:ident, $type_name0:ident, $arg_type0:ty, $type_name1:ident, $arg_type1:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [], []; n; + [], [], []; n; + [(arg0, $type_name0, ($arg_type0)), (arg1, $type_name1, ($arg_type1))] + ); + }; + ($func_name:ident [ $(const $var:ident : $vty:ty),* ], $type_name0:ident, $arg_type0:ty, $type_name1:ident, $arg_type1:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [$(const $var: $vty),*], [$($var),*]; n; + [], [], []; n; + [(arg0, $type_name0, ($arg_type0)), (arg1, $type_name1, ($arg_type1))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name N__N>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: $arg_type2, arg3: Option<$arg_type3> ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg3 = arg3?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// If there exists `f_t0_t1_t2(x: T, y: S, z: V) -> U`, creates the 7 nullable variants. +#[doc(hidden)] +#[macro_export] +macro_rules! some_polymorphic_function3 { + ($func_name:ident, $type_name0:ident, $arg_type0:ty, $type_name1:ident, $arg_type1:ty, $type_name2:ident, $arg_type2:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [], []; y; + [], [], []; n; + [(arg0, $type_name0, ($arg_type0)), (arg1, $type_name1, ($arg_type1)), (arg2, $type_name2, ($arg_type2))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name N_N_>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: Option<$arg_type2>, arg3: $arg_type3 ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg2 = arg2?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// Like [`some_polymorphic_function3`], but the base function already returns +/// `Option`, so wrappers return it directly without an extra `Some()`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_polymorphic_null_function3 { + ($func_name:ident, $type_name0:ident, $arg_type0:ty, $type_name1:ident, $arg_type1:ty, $type_name2:ident, $arg_type2:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [], []; n; + [], [], []; n; + [(arg0, $type_name0, ($arg_type0)), (arg1, $type_name1, ($arg_type1)), (arg2, $type_name2, ($arg_type2))] + ); + }; + ($func_name:ident [ $(const $var:ident : $vty:ty),* ], $type_name0:ident, $arg_type0:ty, $type_name1:ident, $arg_type1:ty, $type_name2:ident, $arg_type2:ty, $ret_type:ty) => { + $crate::some_polymorphic_function_impl!(@step $func_name, $ret_type, + [$(const $var: $vty),*], [$($var),*]; n; + [], [], []; n; + [(arg0, $type_name0, ($arg_type0)), (arg1, $type_name1, ($arg_type1)), (arg2, $type_name2, ($arg_type2))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name N_NN>]( arg0: Option<$arg_type0>, arg1: $arg_type1, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg2 = arg2?; - let arg3 = arg3?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// Macro to create variants of a function with 3 arguments. +/// If there exists a function `f___(x: T, y: S, z: V) -> U`, this creates +/// the 7 nullable variants (all combinations except all-non-nullable). +/// Each generated function returns `None` when any argument is `None`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_function3 { + ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $arg_type2:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [], [], []; y; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1)), (arg2, ($arg_type2))] + ); + }; + ($func_name:ident [$($tgen:tt)*], $arg_type0:ty, $arg_type1:ty, $arg_type2:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [$($tgen)*], [], []; y; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1)), (arg2, ($arg_type2))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name NN__>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: $arg_type2, arg3: $arg_type3 ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// Macro to create variants of a function with 4 arguments. +/// If there exists a function `f____(x: T, y: S, z: V, w: W) -> U`, this +/// creates the 15 nullable variants (all combinations except all-non-nullable). +/// Each generated function returns `None` when any argument is `None`. +#[doc(hidden)] +#[macro_export] +macro_rules! some_function4 { + ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $arg_type2:ty, $arg_type3:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [], [], []; y; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1)), (arg2, ($arg_type2)), (arg3, ($arg_type3))] + ); + }; + ($func_name:ident [$($tgen:tt)*], $arg_type0:ty, $arg_type1:ty, $arg_type2:ty, $arg_type3:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [$($tgen)*], [], []; y; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1)), (arg2, ($arg_type2)), (arg3, ($arg_type3))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name NN_N>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: $arg_type2, arg3: Option<$arg_type3> ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - let arg3 = arg3?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// Like [`some_function1`] but for a base function that already returns `Option`. +/// If there exists `f_(x: T) -> Option`, creates: +/// - `fN(x: Option) -> Option` +#[doc(hidden)] +#[macro_export] +macro_rules! some_nullable_function1 { + ($func_name:ident, $arg_type:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [], [], []; n; n; + [(arg0, ($arg_type))] + ); + }; + ($func_name:ident [$($tgen:tt)*], $arg_type:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [$($tgen)*], [], []; n; n; + [(arg0, ($arg_type))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name NNN_>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: $arg_type3 ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - let arg2 = arg2?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } +/// Like [`some_function2`] but for a base function that already returns `Option`. +/// If there exists `f__(x: T, y: S) -> Option`, creates: +/// - `f_N`, `fN_`, `fNN` +#[doc(hidden)] +#[macro_export] +macro_rules! some_nullable_function2 { + ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [], [], []; n; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1))] + ); + }; + ($func_name:ident [$($tgen:tt)*], $arg_type0:ty, $arg_type1:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [$($tgen)*], [], []; n; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1))] + ); + }; +} - #[doc(hidden)] - pub fn [<$func_name NNNN>]( arg0: Option<$arg_type0>, arg1: Option<$arg_type1>, arg2: Option<$arg_type2>, arg3: Option<$arg_type3> ) -> Option<$ret_type> { - let arg0 = arg0?; - let arg1 = arg1?; - let arg2 = arg2?; - let arg3 = arg3?; - Some([<$func_name ____>](arg0, arg1, arg2, arg3)) - } - } - } +/// Like [`some_function3`] but for a base function that already returns `Option`. +/// If there exists `f___(x: T, y: S, z: V) -> Option`, creates the 7 nullable variants. +#[doc(hidden)] +#[macro_export] +macro_rules! some_nullable_function3 { + ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $arg_type2:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [], [], []; n; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1)), (arg2, ($arg_type2))] + ); + }; + ($func_name:ident [$($tgen:tt)*], $arg_type0:ty, $arg_type1:ty, $arg_type2:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [$($tgen)*], [], []; n; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1)), (arg2, ($arg_type2))] + ); + }; } -pub(crate) use some_function4; +/// Like [`some_function4`] but for a base function that already returns `Option`. +/// If there exists `f____(x: T, y: S, z: V, w: W) -> Option`, creates the 15 nullable variants. +#[doc(hidden)] +#[macro_export] +macro_rules! some_nullable_function4 { + ($func_name:ident, $arg_type0:ty, $arg_type1:ty, $arg_type2:ty, $arg_type3:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [], [], []; n; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1)), (arg2, ($arg_type2)), (arg3, ($arg_type3))] + ); + }; + ($func_name:ident [$($tgen:tt)*], $arg_type0:ty, $arg_type1:ty, $arg_type2:ty, $arg_type3:ty, $ret_type:ty) => { + $crate::some_function_impl!(@step $func_name, $ret_type, [$($tgen)*], [], []; n; n; + [(arg0, ($arg_type0)), (arg1, ($arg_type1)), (arg2, ($arg_type2)), (arg3, ($arg_type3))] + ); + }; +} /// Macro to create variants of a function with 2 arguments /// optimized for the implementation of arithmetic operators. diff --git a/crates/sqllib/src/map.rs b/crates/sqllib/src/map.rs index 97eeeb50b2..bae0e80ebd 100644 --- a/crates/sqllib/src/map.rs +++ b/crates/sqllib/src/map.rs @@ -1,7 +1,7 @@ //! Functions for manipulating maps use crate::error::{SqlResult, SqlRuntimeError}; -use crate::{Array, ConcatSemigroup, Semigroup, Weight}; +use crate::{Array, ConcatSemigroup, Semigroup, Weight, some_function1, some_function2}; use dbsp::utils::Tup2; use std::collections::BTreeMap; use std::sync::Arc; @@ -285,34 +285,7 @@ where value.contains_key(&key) } -#[doc(hidden)] -pub fn map_contains_keyN_(value: Option>, key: I) -> Option -where - I: Ord, - T: Clone, -{ - value.map(|map| map_contains_key__(map, key)) -} - -#[doc(hidden)] -pub fn map_contains_keyNN(value: Option>, key: Option) -> Option -where - I: Ord, - T: Clone, -{ - let key = key?; - map_contains_keyN_(value, key) -} - -#[doc(hidden)] -pub fn map_contains_key_N(value: Map, key: Option) -> Option -where - I: Ord, - T: Clone, -{ - let key = key?; - Some(map_contains_key__(value, key)) -} +some_function2!(map_contains_key [I: Ord, T: Clone], Map, I, bool); #[doc(hidden)] pub fn map_keys_(value: Map) -> Array @@ -339,11 +312,4 @@ where Arc::new(value.values().cloned().collect()) } -#[doc(hidden)] -pub fn map_valuesN(value: Option>) -> Option> -where - I: Ord + Clone, - T: Clone, -{ - value.map(|value| map_values_(value)) -} +some_function1!(map_values [I: Ord + Clone, T: Clone], Map, Array); diff --git a/crates/sqllib/src/operators.rs b/crates/sqllib/src/operators.rs index 7e2f246007..a5b0b09518 100644 --- a/crates/sqllib/src/operators.rs +++ b/crates/sqllib/src/operators.rs @@ -5,7 +5,7 @@ use num::{Float, PrimInt, Zero}; use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub}; use std::cmp::Ordering; -use crate::{some_existing_operator, some_operator, type_name}; +use crate::{some_existing_operator, some_operator, some_polymorphic_null_function2, type_name}; macro_rules! for_all_int_operator { ($func_name: ident) => { @@ -475,27 +475,7 @@ pub fn div_null_d_d(left: F64, right: F64) -> Option { finite_or_null(result).map(|x| x.into()) } -#[inline(always)] -#[doc(hidden)] -pub fn div_null_dN_d(left: Option, right: F64) -> Option { - let left = left?; - div_null_d_d(left, right) -} - -#[inline(always)] -#[doc(hidden)] -pub fn div_null_d_dN(left: F64, right: Option) -> Option { - let right = right?; - div_null_d_d(left, right) -} - -#[inline(always)] -#[doc(hidden)] -pub fn div_null_dN_dN(left: Option, right: Option) -> Option { - let left = left?; - let right = right?; - div_null_d_d(left, right) -} +some_polymorphic_null_function2!(div_null, d, F64, d, F64, F64); #[inline(always)] #[doc(hidden)] @@ -504,27 +484,7 @@ pub fn div_null_f_f(left: F32, right: F32) -> Option { finite_or_null(result).map(|x| x.into()) } -#[inline(always)] -#[doc(hidden)] -pub fn div_null_fN_f(left: Option, right: F32) -> Option { - let left = left?; - div_null_f_f(left, right) -} - -#[inline(always)] -#[doc(hidden)] -pub fn div_null_f_fN(left: F32, right: Option) -> Option { - let right = right?; - div_null_f_f(left, right) -} - -#[inline(always)] -#[doc(hidden)] -pub fn div_null_fN_fN(left: Option, right: Option) -> Option { - let left = left?; - let right = right?; - div_null_f_f(left, right) -} +some_polymorphic_null_function2!(div_null, f, F32, f, F32, F32); #[inline(always)] #[doc(hidden)] diff --git a/crates/sqllib/src/string.rs b/crates/sqllib/src/string.rs index 68230e4d2a..c84986dfb7 100644 --- a/crates/sqllib/src/string.rs +++ b/crates/sqllib/src/string.rs @@ -7,7 +7,8 @@ #![allow(non_snake_case)] use crate::{ Variant, array::Array, some_function1, some_function2, some_function3, some_function4, - some_polymorphic_function1, some_polymorphic_function2, string_interner::*, + some_polymorphic_function1, some_polymorphic_function2, some_polymorphic_null_function1, + string_interner::*, }; use arcstr::ArcStr; @@ -706,11 +707,7 @@ pub fn to_json_V(value: Variant) -> Option { } } -#[doc(hidden)] -pub fn to_json_VN(value: Option) -> Option { - let value = value?; - to_json_V(value) -} +some_polymorphic_null_function1!(to_json, V, Variant, SqlString); #[doc(hidden)] pub fn to_json_nullN(_value: Option<()>) -> Option { diff --git a/crates/sqllib/src/timestamp.rs b/crates/sqllib/src/timestamp.rs index a888912443..2777bee5b7 100644 --- a/crates/sqllib/src/timestamp.rs +++ b/crates/sqllib/src/timestamp.rs @@ -32,8 +32,9 @@ use std::{ use crate::{ operators::{eq, gt, gte, lt, lte, neq}, - some_existing_operator, some_function2, some_operator, some_polymorphic_function1, - some_polymorphic_function2, some_polymorphic_function3, some_polymorphic_null_function3, + some_existing_operator, some_function1, some_function2, some_nullable_function2, + some_nullable_function3, some_operator, some_polymorphic_function1, some_polymorphic_function2, + some_polymorphic_function3, some_polymorphic_null_function3, }; ///////////////////////////////////////////////////////////////////////////////////////////// @@ -878,11 +879,7 @@ pub fn parse_timezone_(tz: SqlString) -> Zone { Zone::parse(tz.str()) } -#[doc(hidden)] -pub fn parse_timezoneN(tz: Option) -> Option { - let tz = tz?; - Some(parse_timezone_(tz)) -} +some_function1!(parse_timezone, SqlString, Zone); #[doc(hidden)] pub fn convert_timezone___(src_tz: Zone, dst_tz: Zone, ts: Timestamp) -> Option { @@ -892,68 +889,7 @@ pub fn convert_timezone___(src_tz: Zone, dst_tz: Zone, ts: Timestamp) -> Option< Some(Timestamp::from_naiveDateTime(result)) } -#[doc(hidden)] -pub fn convert_timezoneN__(source: Option, target: Zone, ts: Timestamp) -> Option { - let source = source?; - convert_timezone___(source, target, ts) -} - -#[doc(hidden)] -pub fn convert_timezone_N_(source: Zone, target: Option, ts: Timestamp) -> Option { - let target = target?; - convert_timezone___(source, target, ts) -} - -#[doc(hidden)] -pub fn convert_timezoneNN_( - source: Option, - target: Option, - ts: Timestamp, -) -> Option { - let source = source?; - let target = target?; - convert_timezone___(source, target, ts) -} - -#[doc(hidden)] -pub fn convert_timezoneN_N( - source: Option, - target: Zone, - ts: Option, -) -> Option { - let source = source?; - let ts = ts?; - convert_timezone___(source, target, ts) -} - -#[doc(hidden)] -pub fn convert_timezone_NN( - source: Zone, - target: Option, - ts: Option, -) -> Option { - let target = target?; - let ts = ts?; - convert_timezone___(source, target, ts) -} - -#[doc(hidden)] -pub fn convert_timezone__N(source: Zone, target: Zone, ts: Option) -> Option { - let ts = ts?; - convert_timezone___(source, target, ts) -} - -#[doc(hidden)] -pub fn convert_timezoneNNN( - source: Option, - target: Option, - ts: Option, -) -> Option { - let source = source?; - let target = target?; - let ts = ts?; - convert_timezone___(source, target, ts) -} +some_nullable_function3!(convert_timezone, Zone, Zone, Timestamp, Timestamp); #[doc(hidden)] pub fn now() -> Timestamp { @@ -2282,21 +2218,7 @@ pub fn parse_timestamp__(format: SqlString, st: SqlString) -> Option } } -pub fn parse_timestampN_(format: Option, st: SqlString) -> Option { - let format = format?; - parse_timestamp__(format, st) -} - -pub fn parse_timestamp_N(format: SqlString, st: Option) -> Option { - let st = st?; - parse_timestamp__(format, st) -} - -pub fn parse_timestampNN(format: Option, st: Option) -> Option { - let st = st?; - let format = format?; - parse_timestamp__(format, st) -} +some_nullable_function2!(parse_timestamp, SqlString, SqlString, Timestamp); ///////////////////////////////////////////////////////////////////////////////////////////// // Date @@ -2514,52 +2436,7 @@ pub fn make_date___(year: i32, month: i32, day: i32) -> Option { Some(Date::from_date(naive)) } -#[doc(hidden)] -pub fn make_dateN__(year: Option, month: i32, day: i32) -> Option { - let year = year?; - make_date___(year, month, day) -} - -#[doc(hidden)] -pub fn make_date_N_(year: i32, month: Option, day: i32) -> Option { - let month = month?; - make_date___(year, month, day) -} - -#[doc(hidden)] -pub fn make_date__N(year: i32, month: i32, day: Option) -> Option { - let day = day?; - make_date___(year, month, day) -} - -#[doc(hidden)] -pub fn make_dateNN_(year: Option, month: Option, day: i32) -> Option { - let year = year?; - let month = month?; - make_date___(year, month, day) -} - -#[doc(hidden)] -pub fn make_date_NN(year: i32, month: Option, day: Option) -> Option { - let month = month?; - let day = day?; - make_date___(year, month, day) -} - -#[doc(hidden)] -pub fn make_dateN_N(year: Option, month: i32, day: Option) -> Option { - let year = year?; - let day = day?; - make_date___(year, month, day) -} - -#[doc(hidden)] -pub fn make_dateNNN(year: Option, month: Option, day: Option) -> Option { - let year = year?; - let month = month?; - let day = day?; - make_date___(year, month, day) -} +some_nullable_function3!(make_date, i32, i32, i32, Date); #[doc(hidden)] pub fn floor_century_Date(value: Date) -> Date { @@ -3683,7 +3560,7 @@ pub fn make_time_i32_i32_SqlDecimal( Some(Time::from_time(result)) } -some_polymorphic_null_function3!(make_time , i32, i32, i32, i32, SqlDecimal, SqlDecimal, Time); +some_polymorphic_null_function3!(make_time [const P: usize, const S: usize], i32, i32, i32, i32, SqlDecimal, SqlDecimal, Time); #[doc(hidden)] pub fn floor_millennium_Time(value: Time) -> Time {