From a3896e54701586fec2fadd011c0abdb806e56461 Mon Sep 17 00:00:00 2001 From: taichong Date: Thu, 2 Jan 2025 11:47:06 +0800 Subject: [PATCH 1/2] chore: try split number cast function impl --- Cargo.lock | 12 +- Cargo.toml | 2 + src/query/functions/Cargo.toml | 1 + .../src/scalars/arithmetic/src/arithmetic.rs | 434 ++++++++++-------- .../src/scalars/integer_arithmetic/Cargo.toml | 13 + .../src/integer_arithmetic.rs | 49 ++ .../src/scalars/integer_arithmetic/src/lib.rs | 29 ++ src/query/functions/src/scalars/mod.rs | 2 + .../numeric_basic_arithmetic/Cargo.toml | 1 - .../numeric_basic_arithmetic/src/lib.rs | 6 +- .../src/numeric_basic_arithmetic.rs | 130 ++++-- 11 files changed, 434 insertions(+), 245 deletions(-) create mode 100644 src/query/functions/src/scalars/integer_arithmetic/Cargo.toml create mode 100644 src/query/functions/src/scalars/integer_arithmetic/src/integer_arithmetic.rs create mode 100644 src/query/functions/src/scalars/integer_arithmetic/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 3d0b2ad72030d..f04c0555444a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3383,6 +3383,7 @@ dependencies = [ "databend-functions-scalar-datetime", "databend-functions-scalar-decimal", "databend-functions-scalar-geo", + "databend-functions-scalar-integer-basic-arithmetic", "databend-functions-scalar-math", "databend-functions-scalar-numeric-basic-arithmetic", "ethnum", @@ -4876,6 +4877,16 @@ dependencies = [ "proj4rs", ] +[[package]] +name = "databend-functions-scalar-integer-basic-arithmetic" +version = "0.1.0" +dependencies = [ + "databend-common-expression", + "databend-functions-scalar-numeric-basic-arithmetic", + "match-template", + "num-traits", +] + [[package]] name = "databend-functions-scalar-math" version = "0.1.0" @@ -4893,7 +4904,6 @@ name = "databend-functions-scalar-numeric-basic-arithmetic" version = "0.1.0" dependencies = [ "databend-common-expression", - "databend-functions-scalar-decimal", "match-template", "num-traits", "strength_reduce", diff --git a/Cargo.toml b/Cargo.toml index 53dc13f0e4afe..65684d2a39ee9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ members = [ "src/query/functions/src/scalars/timestamp", "src/query/functions/src/scalars/numeric_basic_arithmetic", "src/query/functions/src/scalars/arithmetic", + "src/query/functions/src/scalars/integer_arithmetic", "src/query/management", "src/query/pipeline/core", "src/query/pipeline/sinks", @@ -194,6 +195,7 @@ databend-functions-scalar-arithmetic = { path = "src/query/functions/src/scalars databend-functions-scalar-datetime = { path = "src/query/functions/src/scalars/timestamp" } databend-functions-scalar-decimal = { path = "src/query/functions/src/scalars/decimal" } databend-functions-scalar-geo = { path = "src/query/functions/src/scalars/geographic" } +databend-functions-scalar-integer-basic-arithmetic = { path = "src/query/functions/src/scalars/integer_arithmetic" } databend-functions-scalar-math = { path = "src/query/functions/src/scalars/mathematics" } databend-functions-scalar-numeric-basic-arithmetic = { path = "src/query/functions/src/scalars/numeric_basic_arithmetic" } databend-meta = { path = "src/meta/service" } diff --git a/src/query/functions/Cargo.toml b/src/query/functions/Cargo.toml index 5f5c8e30aa0fe..69d31efe89334 100644 --- a/src/query/functions/Cargo.toml +++ b/src/query/functions/Cargo.toml @@ -30,6 +30,7 @@ databend-functions-scalar-arithmetic = { workspace = true } databend-functions-scalar-datetime = { workspace = true } databend-functions-scalar-decimal = { workspace = true } databend-functions-scalar-geo = { workspace = true } +databend-functions-scalar-integer-basic-arithmetic = { workspace = true } databend-functions-scalar-math = { workspace = true } databend-functions-scalar-numeric-basic-arithmetic = { workspace = true } ethnum = { workspace = true } diff --git a/src/query/functions/src/scalars/arithmetic/src/arithmetic.rs b/src/query/functions/src/scalars/arithmetic/src/arithmetic.rs index 4f0446ae3c8c6..7647cb606869d 100644 --- a/src/query/functions/src/scalars/arithmetic/src/arithmetic.rs +++ b/src/query/functions/src/scalars/arithmetic/src/arithmetic.rs @@ -303,197 +303,6 @@ fn register_unary_minus(registry: &mut FunctionRegistry) { } } -pub fn register_number_to_number(registry: &mut FunctionRegistry) { - for dest_type in ALL_NUMERICS_TYPES { - // each out loop register all to_{dest_type} - // dest_type not include decimal - for src_type in ALL_NUMBER_CLASSES { - with_number_mapped_type!(|SRC_TYPE| match src_type { - NumberClass::SRC_TYPE => with_number_mapped_type!(|DEST_TYPE| match dest_type { - NumberDataType::DEST_TYPE => { - let src_type = src_type.get_number_type().unwrap(); - if src_type == *dest_type { - continue; - } - let name = format!("to_{dest_type}").to_lowercase(); - if src_type.can_lossless_cast_to(*dest_type) { - registry.register_1_arg::, NumberType, _, _>( - &name, - |_, domain| { - let (domain, overflowing) = domain.overflow_cast(); - debug_assert!(!overflowing); - FunctionDomain::Domain(domain) - }, - |val, _| val.as_() - ); - } else if src_type.need_round_cast_to(*dest_type) { - registry.register_passthrough_nullable_1_arg::, NumberType, _, _>( - &name, - |func_ctx, domain| { - let (domain, overflowing) = if func_ctx.rounding_mode { - // Perform round on domain to keep the result of domain - // matches the result of function - let min = AsPrimitive::::as_(domain.min); - let max = AsPrimitive::::as_(domain.max); - let round_domain = SimpleDomain::{ - min: min.round().into(), - max: max.round().into(), - }; - round_domain.overflow_cast() - } else { - domain.overflow_cast() - }; - if overflowing { - FunctionDomain::MayThrow - } else { - FunctionDomain::Domain(domain) - } - }, - vectorize_with_builder_1_arg::, NumberType>( - move |val, output, ctx| { - let val = if ctx.func_ctx.rounding_mode { - let val = AsPrimitive::::as_(val); - num_traits::cast::cast(val.round()) - } else { - num_traits::cast::cast(val) - }; - if let Some(new_val) = val { - output.push(new_val); - } else { - ctx.set_error(output.len(),"number overflowed"); - output.push(DEST_TYPE::default()); - } - } - ), - ); - } else { - registry.register_passthrough_nullable_1_arg::, NumberType, _, _>( - &name, - |_, domain| { - let (domain, overflowing) = domain.overflow_cast(); - if overflowing { - FunctionDomain::MayThrow - } else { - FunctionDomain::Domain(domain) - } - }, - vectorize_with_builder_1_arg::, NumberType>( - move |val, output, ctx| { - if let Some(new_val) = num_traits::cast::cast(val) { - output.push(new_val); - } else { - ctx.set_error(output.len(),"number overflowed"); - output.push(DEST_TYPE::default()); - } - } - ), - ); - } - - let name = format!("try_to_{dest_type}").to_lowercase(); - if src_type.can_lossless_cast_to(*dest_type) { - registry.register_combine_nullable_1_arg::, NumberType, _, _>( - &name, - |_, domain| { - let (domain, overflowing) = domain.overflow_cast(); - debug_assert!(!overflowing); - FunctionDomain::Domain(NullableDomain { - has_null: false, - value: Some(Box::new( - domain, - )), - }) - }, - vectorize_1_arg::, NullableType>>(|val, _| { - Some(val.as_()) - }) - ); - } else if src_type.need_round_cast_to(*dest_type) { - registry.register_combine_nullable_1_arg::, NumberType, _, _>( - &name, - |func_ctx, domain| { - let (domain, overflowing) = if func_ctx.rounding_mode { - // Perform round on domain to keep the result of domain - // matches the result of function - let min = AsPrimitive::::as_(domain.min); - let max = AsPrimitive::::as_(domain.max); - let round_domain = SimpleDomain::{ - min: min.round().into(), - max: max.round().into(), - }; - round_domain.overflow_cast() - } else { - domain.overflow_cast() - }; - FunctionDomain::Domain(NullableDomain { - has_null: overflowing, - value: Some(Box::new( - domain, - )), - }) - }, - vectorize_with_builder_1_arg::, NullableType>>( - |val, output, ctx| { - let val = if ctx.func_ctx.rounding_mode { - let val = AsPrimitive::::as_(val); - num_traits::cast::cast(val.round()) - } else { - num_traits::cast::cast(val) - }; - if let Some(new_val) = val { - output.push(new_val); - } else { - output.push_null(); - } - } - ), - ); - } else { - registry.register_combine_nullable_1_arg::, NumberType, _, _>( - &name, - |_, domain| { - let (domain, overflowing) = domain.overflow_cast(); - FunctionDomain::Domain(NullableDomain { - has_null: overflowing, - value: Some(Box::new( - domain, - )), - }) - }, - vectorize_with_builder_1_arg::, NullableType>>( - |val, output, _| { - if let Some(new_val) = num_traits::cast::cast(val) { - output.push(new_val); - } else { - output.push_null(); - } - } - ), - ); - } - } - }), - NumberClass::Decimal128 => { - // todo(youngsofun): add decimal try_cast and decimal to int and float - if matches!(dest_type, NumberDataType::Float32) { - register_decimal_to_float::(registry); - } - if matches!(dest_type, NumberDataType::Float64) { - register_decimal_to_float::(registry); - } - - with_number_mapped_type!(|DEST_TYPE| match dest_type { - NumberDataType::DEST_TYPE => register_decimal_to_int::(registry), - }) - } - NumberClass::Decimal256 => { - // already registered in Decimal128 branch - } - }) - } - } -} - pub fn register_decimal_minus(registry: &mut FunctionRegistry) { registry.register_function_factory("minus", |_params, args_type| { if args_type.len() != 1 { @@ -723,3 +532,246 @@ pub fn register_number_to_string(registry: &mut FunctionRegistry) { }); } } + +pub fn register_number_to_number(registry: &mut FunctionRegistry) { + for dest_type in ALL_NUMERICS_TYPES { + // each out loop register all to_{dest_type} + // dest_type not include decimal + for src_type in ALL_NUMBER_CLASSES { + with_number_mapped_type!(|SRC_TYPE| match src_type { + NumberClass::SRC_TYPE => with_number_mapped_type!(|DEST_TYPE| match dest_type { + NumberDataType::DEST_TYPE => { + let src_type = src_type.get_number_type().unwrap(); + if src_type == *dest_type { + continue; + } + let name = format!("to_{dest_type}").to_lowercase(); + if src_type.can_lossless_cast_to(*dest_type) { + register_lossless_cast::(registry, &name); + } else if src_type.need_round_cast_to(*dest_type) { + register_round_cast::(registry, &name); + } else { + register_lossy_cast::(registry, &name); + } + + let name = format!("try_to_{dest_type}").to_lowercase(); + if src_type.can_lossless_cast_to(*dest_type) { + register_try_lossless_cast::(registry, &name); + } else if src_type.need_round_cast_to(*dest_type) { + register_try_round_cast::(registry, &name); + } else { + register_try_lossy_cast::(registry, &name); + } + } + }), + NumberClass::Decimal128 => { + // todo(youngsofun): add decimal try_cast and decimal to int and float + if matches!(dest_type, NumberDataType::Float32) { + register_decimal_to_float::(registry); + } + if matches!(dest_type, NumberDataType::Float64) { + register_decimal_to_float::(registry); + } + + with_number_mapped_type!(|DEST_TYPE| match dest_type { + NumberDataType::DEST_TYPE => register_decimal_to_int::(registry), + }) + } + NumberClass::Decimal256 => { + // already registered in Decimal128 branch + } + }) + } + } +} + +fn register_lossless_cast< + SrcType: Number + AsPrimitive, + DestType: Number + AsPrimitive, +>( + registry: &mut FunctionRegistry, + name: &str, +) { + registry.register_1_arg::, NumberType, _, _>( + name, + |_, domain| { + let (domain, overflowing) = domain.overflow_cast(); + debug_assert!(!overflowing); + FunctionDomain::Domain(domain) + }, + |val, _| AsPrimitive::::as_(val), + ); +} + +fn register_round_cast< + SrcType: Number + AsPrimitive + AsPrimitive, + DestType: Number + AsPrimitive, +>( + registry: &mut FunctionRegistry, + name: &str, +) { + registry + .register_passthrough_nullable_1_arg::, NumberType, _, _>( + name, + |func_ctx, domain| { + let (domain, overflowing) = if func_ctx.rounding_mode { + let min = AsPrimitive::::as_(domain.min); + let max = AsPrimitive::::as_(domain.max); + let round_domain = SimpleDomain:: { + min: min.round().into(), + max: max.round().into(), + }; + round_domain.overflow_cast() + } else { + domain.overflow_cast() + }; + if overflowing { + FunctionDomain::MayThrow + } else { + FunctionDomain::Domain(domain) + } + }, + vectorize_with_builder_1_arg::, NumberType>( + move |val, output, ctx| { + let val = if ctx.func_ctx.rounding_mode { + let val = AsPrimitive::::as_(val); + num_traits::cast::cast(val.round()) + } else { + num_traits::cast::cast(val) + }; + if let Some(new_val) = val { + output.push(new_val); + } else { + ctx.set_error(output.len(), "number overflowed"); + output.push(DestType::default()); + } + }, + ), + ); +} + +fn register_lossy_cast< + SrcType: Number + AsPrimitive, + DestType: Number + AsPrimitive, +>( + registry: &mut FunctionRegistry, + name: &str, +) { + registry + .register_passthrough_nullable_1_arg::, NumberType, _, _>( + name, + |_, domain| { + let (domain, overflowing) = domain.overflow_cast(); + if overflowing { + FunctionDomain::MayThrow + } else { + FunctionDomain::Domain(domain) + } + }, + vectorize_with_builder_1_arg::, NumberType>( + move |val, output, ctx| { + if let Some(new_val) = num_traits::cast::cast(val) { + output.push(new_val); + } else { + ctx.set_error(output.len(), "number overflowed"); + output.push(DestType::default()); + } + }, + ), + ); +} + +fn register_try_lossless_cast< + SrcType: Number + AsPrimitive, + DestType: Number + AsPrimitive, +>( + registry: &mut FunctionRegistry, + name: &str, +) { + registry.register_combine_nullable_1_arg::, NumberType, _, _>( + name, + |_, domain| { + let (domain, overflowing) = domain.overflow_cast(); + debug_assert!(!overflowing); + FunctionDomain::Domain(NullableDomain { + has_null: false, + value: Some(Box::new(domain)), + }) + }, + vectorize_1_arg::, NullableType>>(|val, _| { + Some(val.as_()) + }), + ); +} + +fn register_try_round_cast< + SrcType: Number + AsPrimitive + AsPrimitive, + DestType: Number + AsPrimitive, +>( + registry: &mut FunctionRegistry, + name: &str, +) { + registry.register_combine_nullable_1_arg::, NumberType, _, _>( + name, + |func_ctx, domain| { + let (domain, overflowing) = if func_ctx.rounding_mode { + let min = AsPrimitive::::as_(domain.min); + let max = AsPrimitive::::as_(domain.max); + let round_domain = SimpleDomain:: { + min: min.round().into(), + max: max.round().into(), + }; + round_domain.overflow_cast() + } else { + domain.overflow_cast() + }; + FunctionDomain::Domain(NullableDomain { + has_null: overflowing, + value: Some(Box::new(domain)), + }) + }, + vectorize_with_builder_1_arg::, NullableType>>( + |val, output, ctx| { + let val = if ctx.func_ctx.rounding_mode { + let val = AsPrimitive::::as_(val); + num_traits::cast::cast(val.round()) + } else { + num_traits::cast::cast(val) + }; + if let Some(new_val) = val { + output.push(new_val); + } else { + output.push_null(); + } + }, + ), + ); +} + +fn register_try_lossy_cast< + SrcType: Number + AsPrimitive, + DestType: Number + AsPrimitive, +>( + registry: &mut FunctionRegistry, + name: &str, +) { + registry.register_combine_nullable_1_arg::, NumberType, _, _>( + name, + |_, domain| { + let (domain, overflowing) = domain.overflow_cast(); + FunctionDomain::Domain(NullableDomain { + has_null: overflowing, + value: Some(Box::new(domain)), + }) + }, + vectorize_with_builder_1_arg::, NullableType>>( + |val, output, _| { + if let Some(new_val) = num_traits::cast::cast(val) { + output.push(new_val); + } else { + output.push_null(); + } + }, + ), + ); +} diff --git a/src/query/functions/src/scalars/integer_arithmetic/Cargo.toml b/src/query/functions/src/scalars/integer_arithmetic/Cargo.toml new file mode 100644 index 0000000000000..e4de947242668 --- /dev/null +++ b/src/query/functions/src/scalars/integer_arithmetic/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "databend-functions-scalar-integer-basic-arithmetic" +version = "0.1.0" +edition = "2021" + +[dependencies] +databend-common-expression = { workspace = true } +databend-functions-scalar-numeric-basic-arithmetic = { workspace = true } +match-template = { workspace = true } +num-traits = { workspace = true } + +[package.metadata.cargo-machete] +ignored = ["match-template"] diff --git a/src/query/functions/src/scalars/integer_arithmetic/src/integer_arithmetic.rs b/src/query/functions/src/scalars/integer_arithmetic/src/integer_arithmetic.rs new file mode 100644 index 0000000000000..edae3e26d719e --- /dev/null +++ b/src/query/functions/src/scalars/integer_arithmetic/src/integer_arithmetic.rs @@ -0,0 +1,49 @@ +// Copyright 2021 Datafuse Labs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use databend_common_expression::arithmetics_type::ResultTypeOfBinary; +use databend_common_expression::types::Number; +use databend_common_expression::types::NumberDataType; +use databend_common_expression::types::NumberType; +use databend_common_expression::types::SimpleDomain; +use databend_common_expression::types::ALL_INTEGER_TYPES; +use databend_common_expression::types::F64; +use databend_common_expression::vectorize_with_builder_2_arg; +use databend_common_expression::with_integer_mapped_type; +use databend_common_expression::FunctionDomain; +use databend_common_expression::FunctionRegistry; +use databend_functions_scalar_numeric_basic_arithmetic::register_basic_arithmetic; +use databend_functions_scalar_numeric_basic_arithmetic::register_intdiv; +use databend_functions_scalar_numeric_basic_arithmetic::register_minus; +use databend_functions_scalar_numeric_basic_arithmetic::register_modulo; +use databend_functions_scalar_numeric_basic_arithmetic::register_multiply; +use databend_functions_scalar_numeric_basic_arithmetic::register_plus; +use databend_functions_scalar_numeric_basic_arithmetic::vectorize_modulo; +use num_traits::AsPrimitive; + +pub fn register_integer_basic_arithmetic(registry: &mut FunctionRegistry) { + for left in ALL_INTEGER_TYPES { + for right in ALL_INTEGER_TYPES { + with_integer_mapped_type!(|L| match left { + NumberDataType::L => with_integer_mapped_type!(|R| match right { + NumberDataType::R => { + register_basic_arithmetic!(L, R, registry); + } + _ => unreachable!(), + }), + _ => unreachable!(), + }); + } + } +} diff --git a/src/query/functions/src/scalars/integer_arithmetic/src/lib.rs b/src/query/functions/src/scalars/integer_arithmetic/src/lib.rs new file mode 100644 index 0000000000000..c8e8d39fb31d4 --- /dev/null +++ b/src/query/functions/src/scalars/integer_arithmetic/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright 2021 Datafuse Labs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![allow(clippy::arc_with_non_send_sync)] +#![allow(clippy::uninlined_format_args)] +#![allow(clippy::ptr_arg)] +#![allow(clippy::type_complexity)] +#![allow(internal_features)] +#![feature(core_intrinsics)] +#![feature(box_patterns)] +#![feature(type_ascription)] +#![feature(try_blocks)] +#![feature(downcast_unchecked)] +#![feature(str_internals)] + +pub mod integer_arithmetic; + +pub use integer_arithmetic::*; diff --git a/src/query/functions/src/scalars/mod.rs b/src/query/functions/src/scalars/mod.rs index b83506804d4e3..f529473c52506 100644 --- a/src/query/functions/src/scalars/mod.rs +++ b/src/query/functions/src/scalars/mod.rs @@ -53,6 +53,8 @@ pub fn register(registry: &mut FunctionRegistry) { variant::register(registry); arithmetic::register(registry); // register basic arithmetic operation (+ - * / %) + databend_functions_scalar_decimal::register_decimal_arithmetic(registry); + databend_functions_scalar_integer_basic_arithmetic::register_integer_basic_arithmetic(registry); register_numeric_basic_arithmetic(registry); arithmetic::register_binary_arithmetic(registry); arithmetic::register_unary_arithmetic(registry); diff --git a/src/query/functions/src/scalars/numeric_basic_arithmetic/Cargo.toml b/src/query/functions/src/scalars/numeric_basic_arithmetic/Cargo.toml index 531381213d5fe..f5efcd023d08a 100644 --- a/src/query/functions/src/scalars/numeric_basic_arithmetic/Cargo.toml +++ b/src/query/functions/src/scalars/numeric_basic_arithmetic/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] databend-common-expression = { workspace = true } -databend-functions-scalar-decimal = { workspace = true } match-template = { workspace = true } num-traits = { workspace = true } strength_reduce = { workspace = true } diff --git a/src/query/functions/src/scalars/numeric_basic_arithmetic/src/lib.rs b/src/query/functions/src/scalars/numeric_basic_arithmetic/src/lib.rs index ede7c8cc343c5..cdf2829273b3e 100644 --- a/src/query/functions/src/scalars/numeric_basic_arithmetic/src/lib.rs +++ b/src/query/functions/src/scalars/numeric_basic_arithmetic/src/lib.rs @@ -24,7 +24,11 @@ #![feature(downcast_unchecked)] #![feature(str_internals)] -mod arithmetic_modulo; +pub mod arithmetic_modulo; pub mod numeric_basic_arithmetic; +pub use arithmetic_modulo::vectorize_modulo; +pub use numeric_basic_arithmetic::div0_function; +pub use numeric_basic_arithmetic::divide_function; +pub use numeric_basic_arithmetic::divnull_function; pub use numeric_basic_arithmetic::register_numeric_basic_arithmetic; diff --git a/src/query/functions/src/scalars/numeric_basic_arithmetic/src/numeric_basic_arithmetic.rs b/src/query/functions/src/scalars/numeric_basic_arithmetic/src/numeric_basic_arithmetic.rs index 5328f7f05cd2d..1841d7b142197 100644 --- a/src/query/functions/src/scalars/numeric_basic_arithmetic/src/numeric_basic_arithmetic.rs +++ b/src/query/functions/src/scalars/numeric_basic_arithmetic/src/numeric_basic_arithmetic.rs @@ -26,13 +26,14 @@ use databend_common_expression::vectorize_2_arg; use databend_common_expression::vectorize_with_builder_2_arg; use databend_common_expression::with_float_mapped_type; use databend_common_expression::with_integer_mapped_type; +use databend_common_expression::EvalContext; use databend_common_expression::FunctionDomain; use databend_common_expression::FunctionRegistry; -use databend_functions_scalar_decimal::register_decimal_arithmetic; use num_traits::AsPrimitive; use crate::arithmetic_modulo::vectorize_modulo; +#[macro_export] macro_rules! register_plus { ( $lt:ty, $rt:ty, $registry:expr) => { type L = $lt; @@ -59,6 +60,7 @@ macro_rules! register_plus { }; } +#[macro_export] macro_rules! register_minus { ( $lt:ty, $rt:ty, $registry:expr) => { type L = $lt; @@ -85,6 +87,7 @@ macro_rules! register_minus { }; } +#[macro_export] macro_rules! register_multiply { ( $lt:ty, $rt:ty, $registry:expr) => { type L = $lt; @@ -116,29 +119,47 @@ macro_rules! register_multiply { }; } +pub fn divide_function, R: AsPrimitive>( + a: L, + b: R, + output: &mut Vec, + ctx: &mut EvalContext, +) { + let b_val: F64 = b.as_(); + if std::intrinsics::unlikely(b_val == 0.0) { + ctx.set_error(output.len(), "divided by zero"); + output.push(F64::default()); + } else { + output.push(AsPrimitive::::as_(a) / b_val); + } +} + +#[macro_export] macro_rules! register_divide { ( $lt:ty, $rt:ty, $registry:expr) => { type L = $lt; type R = $rt; type T = F64; - $registry.register_passthrough_nullable_2_arg::, NumberType, NumberType, _, _>( + $registry.register_passthrough_nullable_2_arg::, NumberType, NumberType, _, _>( "divide", - |_, _, _| FunctionDomain::MayThrow, vectorize_with_builder_2_arg::, NumberType, NumberType>( - |a, b, output, ctx| { - let b: T = b.as_(); - if std::intrinsics::unlikely(b == 0.0) { - ctx.set_error(output.len(), "divided by zero"); - output.push(F64::default()); - } else { - output.push(((AsPrimitive::::as_(a)) / b)); - } - }), + |a, b, output, ctx| divide_function(a, b, output, ctx) + ), ); }; } +pub fn div0_function, R: AsPrimitive>(a: L, b: R, output: &mut Vec) { + let b: F64 = b.as_(); + if std::intrinsics::unlikely(b == 0.0) { + output.push(F64::default()); // Push the default value for type T + } else { + output.push(AsPrimitive::::as_(a) / b); + } +} + +#[macro_export] macro_rules! register_div0 { ($lt:ty, $rt:ty, $registry:expr) => { type L = $lt; @@ -149,19 +170,22 @@ macro_rules! register_div0 { "div0", |_, _, _| FunctionDomain::Full, vectorize_with_builder_2_arg::, NumberType, NumberType>( - |a, b, output, _ctx| { - let b: F64 = b.as_(); - if std::intrinsics::unlikely(b == 0.0) { - output.push(T::default()); // Push the default value for type T - } else { - output.push(AsPrimitive::::as_(a) / b); - } - } + |a, b, output, _ctx| div0_function(a, b, output) ), ); }; } +pub fn divnull_function, R: AsPrimitive>(a: L, b: R) -> Option { + let b: F64 = b.as_(); + if std::intrinsics::unlikely(b == 0.0) { + None + } else { + Some(AsPrimitive::::as_(a) / b) + } +} + +#[macro_export] macro_rules! register_divnull { ($lt:ty, $rt:ty, $registry:expr) => { type L = $lt; @@ -174,12 +198,7 @@ macro_rules! register_divnull { vectorize_2_arg::>, NullableType>, NullableType>>(|a, b, _| { match (a, b) { (Some(a), Some(b)) => { - let b: F64 = b.as_(); - if std::intrinsics::unlikely(b == 0.0) { - None - } else { - Some(AsPrimitive::::as_(a) / b) - } + divnull_function(a,b) }, _ => None, } @@ -187,6 +206,7 @@ macro_rules! register_divnull { } } +#[macro_export] macro_rules! register_intdiv { ( $lt:ty, $rt:ty, $registry:expr) => { type L = $lt; @@ -194,7 +214,6 @@ macro_rules! register_intdiv { type T = <(L, R) as ResultTypeOfBinary>::IntDiv; $registry.register_passthrough_nullable_2_arg::, NumberType, NumberType,_, _>( "div", - |_, _, _| FunctionDomain::MayThrow, vectorize_with_builder_2_arg::, NumberType, NumberType>( |a, b, output, ctx| { @@ -211,6 +230,7 @@ macro_rules! register_intdiv { }; } +#[macro_export] macro_rules! register_modulo { ( $lt:ty, $rt:ty, $registry:expr) => { type L = $lt; @@ -254,6 +274,7 @@ macro_rules! register_modulo { }; } +#[macro_export] macro_rules! register_basic_arithmetic { ( $lt:ty, $rt:ty, $registry:expr) => {{ register_plus!($lt, $rt, $registry); @@ -264,39 +285,46 @@ macro_rules! register_basic_arithmetic { { register_multiply!($lt, $rt, $registry); } - { - register_divide!($lt, $rt, $registry); - } { register_intdiv!($lt, $rt, $registry); } - { - register_div0!($lt, $rt, $registry); - } - { - register_divnull!($lt, $rt, $registry); - } { register_modulo!($lt, $rt, $registry); }}; } -pub fn register_numeric_basic_arithmetic(registry: &mut FunctionRegistry) { - register_decimal_arithmetic(registry); +pub fn register_div_arithmetic(registry: &mut FunctionRegistry) { + registry.register_passthrough_nullable_2_arg::, NumberType, NumberType, _, _>( + "divide", + |_, _, _| FunctionDomain::MayThrow, + vectorize_with_builder_2_arg::, NumberType, NumberType>( + |a, b, output, ctx| divide_function(a, b, output, ctx) + ), + ); - for left in ALL_INTEGER_TYPES { - for right in ALL_INTEGER_TYPES { - with_integer_mapped_type!(|L| match left { - NumberDataType::L => with_integer_mapped_type!(|R| match right { - NumberDataType::R => { - register_basic_arithmetic!(L, R, registry); - } - _ => unreachable!(), - }), - _ => unreachable!(), - }); - } - } + registry.register_passthrough_nullable_2_arg::, NumberType, NumberType, _, _>( + "div0", + |_, _, _| FunctionDomain::Full, + vectorize_with_builder_2_arg::, NumberType, NumberType>( + |a, b, output, _ctx| div0_function(a, b, output) + ), + ); + + registry.register_2_arg_core::>, NullableType>, NullableType>, _, _>( + "divnull", + |_, _, _| FunctionDomain::Full, + vectorize_2_arg::>, NullableType>, NullableType>>(|a, b, _| { + match (a, b) { + (Some(a), Some(b)) => { + divnull_function(a,b) + }, + _ => None, + } + })); +} + +pub fn register_numeric_basic_arithmetic(registry: &mut FunctionRegistry) { + register_div_arithmetic(registry); for left in ALL_INTEGER_TYPES { for right in ALL_FLOAT_TYPES { From de208aabad00cde2f178c831b9feeb7c84454320 Mon Sep 17 00:00:00 2001 From: TCeason Date: Fri, 3 Jan 2025 10:47:08 +0800 Subject: [PATCH 2/2] divnull div0 only register once --- .../src/integer_arithmetic.rs | 2 + .../src/numeric_basic_arithmetic.rs | 17 +- .../it/scalars/testdata/function_list.txt | 303 +----------------- 3 files changed, 11 insertions(+), 311 deletions(-) diff --git a/src/query/functions/src/scalars/integer_arithmetic/src/integer_arithmetic.rs b/src/query/functions/src/scalars/integer_arithmetic/src/integer_arithmetic.rs index edae3e26d719e..ec7e14d6e1539 100644 --- a/src/query/functions/src/scalars/integer_arithmetic/src/integer_arithmetic.rs +++ b/src/query/functions/src/scalars/integer_arithmetic/src/integer_arithmetic.rs @@ -23,7 +23,9 @@ use databend_common_expression::vectorize_with_builder_2_arg; use databend_common_expression::with_integer_mapped_type; use databend_common_expression::FunctionDomain; use databend_common_expression::FunctionRegistry; +use databend_functions_scalar_numeric_basic_arithmetic::numeric_basic_arithmetic::divide_function; use databend_functions_scalar_numeric_basic_arithmetic::register_basic_arithmetic; +use databend_functions_scalar_numeric_basic_arithmetic::register_divide; use databend_functions_scalar_numeric_basic_arithmetic::register_intdiv; use databend_functions_scalar_numeric_basic_arithmetic::register_minus; use databend_functions_scalar_numeric_basic_arithmetic::register_modulo; diff --git a/src/query/functions/src/scalars/numeric_basic_arithmetic/src/numeric_basic_arithmetic.rs b/src/query/functions/src/scalars/numeric_basic_arithmetic/src/numeric_basic_arithmetic.rs index 1841d7b142197..fc9fecff48f53 100644 --- a/src/query/functions/src/scalars/numeric_basic_arithmetic/src/numeric_basic_arithmetic.rs +++ b/src/query/functions/src/scalars/numeric_basic_arithmetic/src/numeric_basic_arithmetic.rs @@ -125,12 +125,12 @@ pub fn divide_function, R: AsPrimitive>( output: &mut Vec, ctx: &mut EvalContext, ) { - let b_val: F64 = b.as_(); - if std::intrinsics::unlikely(b_val == 0.0) { + let b: F64 = b.as_(); + if std::intrinsics::unlikely(b == 0.0) { ctx.set_error(output.len(), "divided by zero"); output.push(F64::default()); } else { - output.push(AsPrimitive::::as_(a) / b_val); + output.push((AsPrimitive::::as_(a)) / b); } } @@ -285,6 +285,9 @@ macro_rules! register_basic_arithmetic { { register_multiply!($lt, $rt, $registry); } + { + register_divide!($lt, $rt, $registry); + } { register_intdiv!($lt, $rt, $registry); } @@ -294,14 +297,6 @@ macro_rules! register_basic_arithmetic { } pub fn register_div_arithmetic(registry: &mut FunctionRegistry) { - registry.register_passthrough_nullable_2_arg::, NumberType, NumberType, _, _>( - "divide", - |_, _, _| FunctionDomain::MayThrow, - vectorize_with_builder_2_arg::, NumberType, NumberType>( - |a, b, output, ctx| divide_function(a, b, output, ctx) - ), - ); - registry.register_passthrough_nullable_2_arg::, NumberType, NumberType, _, _>( "div0", |_, _, _| FunctionDomain::Full, diff --git a/src/query/functions/tests/it/scalars/testdata/function_list.txt b/src/query/functions/tests/it/scalars/testdata/function_list.txt index 52a632f4a4546..f18d7486df983 100644 --- a/src/query/functions/tests/it/scalars/testdata/function_list.txt +++ b/src/query/functions/tests/it/scalars/testdata/function_list.txt @@ -1465,206 +1465,8 @@ Functions overloads: 197 div(Float64 NULL, Float32 NULL) :: Int64 NULL 198 div(Float64, Float64) :: Int64 199 div(Float64 NULL, Float64 NULL) :: Int64 NULL -0 div0(UInt8, UInt8) :: Float64 -1 div0(UInt8 NULL, UInt8 NULL) :: Float64 NULL -2 div0(UInt8, UInt16) :: Float64 -3 div0(UInt8 NULL, UInt16 NULL) :: Float64 NULL -4 div0(UInt8, UInt32) :: Float64 -5 div0(UInt8 NULL, UInt32 NULL) :: Float64 NULL -6 div0(UInt8, UInt64) :: Float64 -7 div0(UInt8 NULL, UInt64 NULL) :: Float64 NULL -8 div0(UInt8, Int8) :: Float64 -9 div0(UInt8 NULL, Int8 NULL) :: Float64 NULL -10 div0(UInt8, Int16) :: Float64 -11 div0(UInt8 NULL, Int16 NULL) :: Float64 NULL -12 div0(UInt8, Int32) :: Float64 -13 div0(UInt8 NULL, Int32 NULL) :: Float64 NULL -14 div0(UInt8, Int64) :: Float64 -15 div0(UInt8 NULL, Int64 NULL) :: Float64 NULL -16 div0(UInt16, UInt8) :: Float64 -17 div0(UInt16 NULL, UInt8 NULL) :: Float64 NULL -18 div0(UInt16, UInt16) :: Float64 -19 div0(UInt16 NULL, UInt16 NULL) :: Float64 NULL -20 div0(UInt16, UInt32) :: Float64 -21 div0(UInt16 NULL, UInt32 NULL) :: Float64 NULL -22 div0(UInt16, UInt64) :: Float64 -23 div0(UInt16 NULL, UInt64 NULL) :: Float64 NULL -24 div0(UInt16, Int8) :: Float64 -25 div0(UInt16 NULL, Int8 NULL) :: Float64 NULL -26 div0(UInt16, Int16) :: Float64 -27 div0(UInt16 NULL, Int16 NULL) :: Float64 NULL -28 div0(UInt16, Int32) :: Float64 -29 div0(UInt16 NULL, Int32 NULL) :: Float64 NULL -30 div0(UInt16, Int64) :: Float64 -31 div0(UInt16 NULL, Int64 NULL) :: Float64 NULL -32 div0(UInt32, UInt8) :: Float64 -33 div0(UInt32 NULL, UInt8 NULL) :: Float64 NULL -34 div0(UInt32, UInt16) :: Float64 -35 div0(UInt32 NULL, UInt16 NULL) :: Float64 NULL -36 div0(UInt32, UInt32) :: Float64 -37 div0(UInt32 NULL, UInt32 NULL) :: Float64 NULL -38 div0(UInt32, UInt64) :: Float64 -39 div0(UInt32 NULL, UInt64 NULL) :: Float64 NULL -40 div0(UInt32, Int8) :: Float64 -41 div0(UInt32 NULL, Int8 NULL) :: Float64 NULL -42 div0(UInt32, Int16) :: Float64 -43 div0(UInt32 NULL, Int16 NULL) :: Float64 NULL -44 div0(UInt32, Int32) :: Float64 -45 div0(UInt32 NULL, Int32 NULL) :: Float64 NULL -46 div0(UInt32, Int64) :: Float64 -47 div0(UInt32 NULL, Int64 NULL) :: Float64 NULL -48 div0(UInt64, UInt8) :: Float64 -49 div0(UInt64 NULL, UInt8 NULL) :: Float64 NULL -50 div0(UInt64, UInt16) :: Float64 -51 div0(UInt64 NULL, UInt16 NULL) :: Float64 NULL -52 div0(UInt64, UInt32) :: Float64 -53 div0(UInt64 NULL, UInt32 NULL) :: Float64 NULL -54 div0(UInt64, UInt64) :: Float64 -55 div0(UInt64 NULL, UInt64 NULL) :: Float64 NULL -56 div0(UInt64, Int8) :: Float64 -57 div0(UInt64 NULL, Int8 NULL) :: Float64 NULL -58 div0(UInt64, Int16) :: Float64 -59 div0(UInt64 NULL, Int16 NULL) :: Float64 NULL -60 div0(UInt64, Int32) :: Float64 -61 div0(UInt64 NULL, Int32 NULL) :: Float64 NULL -62 div0(UInt64, Int64) :: Float64 -63 div0(UInt64 NULL, Int64 NULL) :: Float64 NULL -64 div0(Int8, UInt8) :: Float64 -65 div0(Int8 NULL, UInt8 NULL) :: Float64 NULL -66 div0(Int8, UInt16) :: Float64 -67 div0(Int8 NULL, UInt16 NULL) :: Float64 NULL -68 div0(Int8, UInt32) :: Float64 -69 div0(Int8 NULL, UInt32 NULL) :: Float64 NULL -70 div0(Int8, UInt64) :: Float64 -71 div0(Int8 NULL, UInt64 NULL) :: Float64 NULL -72 div0(Int8, Int8) :: Float64 -73 div0(Int8 NULL, Int8 NULL) :: Float64 NULL -74 div0(Int8, Int16) :: Float64 -75 div0(Int8 NULL, Int16 NULL) :: Float64 NULL -76 div0(Int8, Int32) :: Float64 -77 div0(Int8 NULL, Int32 NULL) :: Float64 NULL -78 div0(Int8, Int64) :: Float64 -79 div0(Int8 NULL, Int64 NULL) :: Float64 NULL -80 div0(Int16, UInt8) :: Float64 -81 div0(Int16 NULL, UInt8 NULL) :: Float64 NULL -82 div0(Int16, UInt16) :: Float64 -83 div0(Int16 NULL, UInt16 NULL) :: Float64 NULL -84 div0(Int16, UInt32) :: Float64 -85 div0(Int16 NULL, UInt32 NULL) :: Float64 NULL -86 div0(Int16, UInt64) :: Float64 -87 div0(Int16 NULL, UInt64 NULL) :: Float64 NULL -88 div0(Int16, Int8) :: Float64 -89 div0(Int16 NULL, Int8 NULL) :: Float64 NULL -90 div0(Int16, Int16) :: Float64 -91 div0(Int16 NULL, Int16 NULL) :: Float64 NULL -92 div0(Int16, Int32) :: Float64 -93 div0(Int16 NULL, Int32 NULL) :: Float64 NULL -94 div0(Int16, Int64) :: Float64 -95 div0(Int16 NULL, Int64 NULL) :: Float64 NULL -96 div0(Int32, UInt8) :: Float64 -97 div0(Int32 NULL, UInt8 NULL) :: Float64 NULL -98 div0(Int32, UInt16) :: Float64 -99 div0(Int32 NULL, UInt16 NULL) :: Float64 NULL -100 div0(Int32, UInt32) :: Float64 -101 div0(Int32 NULL, UInt32 NULL) :: Float64 NULL -102 div0(Int32, UInt64) :: Float64 -103 div0(Int32 NULL, UInt64 NULL) :: Float64 NULL -104 div0(Int32, Int8) :: Float64 -105 div0(Int32 NULL, Int8 NULL) :: Float64 NULL -106 div0(Int32, Int16) :: Float64 -107 div0(Int32 NULL, Int16 NULL) :: Float64 NULL -108 div0(Int32, Int32) :: Float64 -109 div0(Int32 NULL, Int32 NULL) :: Float64 NULL -110 div0(Int32, Int64) :: Float64 -111 div0(Int32 NULL, Int64 NULL) :: Float64 NULL -112 div0(Int64, UInt8) :: Float64 -113 div0(Int64 NULL, UInt8 NULL) :: Float64 NULL -114 div0(Int64, UInt16) :: Float64 -115 div0(Int64 NULL, UInt16 NULL) :: Float64 NULL -116 div0(Int64, UInt32) :: Float64 -117 div0(Int64 NULL, UInt32 NULL) :: Float64 NULL -118 div0(Int64, UInt64) :: Float64 -119 div0(Int64 NULL, UInt64 NULL) :: Float64 NULL -120 div0(Int64, Int8) :: Float64 -121 div0(Int64 NULL, Int8 NULL) :: Float64 NULL -122 div0(Int64, Int16) :: Float64 -123 div0(Int64 NULL, Int16 NULL) :: Float64 NULL -124 div0(Int64, Int32) :: Float64 -125 div0(Int64 NULL, Int32 NULL) :: Float64 NULL -126 div0(Int64, Int64) :: Float64 -127 div0(Int64 NULL, Int64 NULL) :: Float64 NULL -128 div0(UInt8, Float32) :: Float64 -129 div0(UInt8 NULL, Float32 NULL) :: Float64 NULL -130 div0(UInt8, Float64) :: Float64 -131 div0(UInt8 NULL, Float64 NULL) :: Float64 NULL -132 div0(UInt16, Float32) :: Float64 -133 div0(UInt16 NULL, Float32 NULL) :: Float64 NULL -134 div0(UInt16, Float64) :: Float64 -135 div0(UInt16 NULL, Float64 NULL) :: Float64 NULL -136 div0(UInt32, Float32) :: Float64 -137 div0(UInt32 NULL, Float32 NULL) :: Float64 NULL -138 div0(UInt32, Float64) :: Float64 -139 div0(UInt32 NULL, Float64 NULL) :: Float64 NULL -140 div0(UInt64, Float32) :: Float64 -141 div0(UInt64 NULL, Float32 NULL) :: Float64 NULL -142 div0(UInt64, Float64) :: Float64 -143 div0(UInt64 NULL, Float64 NULL) :: Float64 NULL -144 div0(Int8, Float32) :: Float64 -145 div0(Int8 NULL, Float32 NULL) :: Float64 NULL -146 div0(Int8, Float64) :: Float64 -147 div0(Int8 NULL, Float64 NULL) :: Float64 NULL -148 div0(Int16, Float32) :: Float64 -149 div0(Int16 NULL, Float32 NULL) :: Float64 NULL -150 div0(Int16, Float64) :: Float64 -151 div0(Int16 NULL, Float64 NULL) :: Float64 NULL -152 div0(Int32, Float32) :: Float64 -153 div0(Int32 NULL, Float32 NULL) :: Float64 NULL -154 div0(Int32, Float64) :: Float64 -155 div0(Int32 NULL, Float64 NULL) :: Float64 NULL -156 div0(Int64, Float32) :: Float64 -157 div0(Int64 NULL, Float32 NULL) :: Float64 NULL -158 div0(Int64, Float64) :: Float64 -159 div0(Int64 NULL, Float64 NULL) :: Float64 NULL -160 div0(Float32, UInt8) :: Float64 -161 div0(Float32 NULL, UInt8 NULL) :: Float64 NULL -162 div0(Float32, UInt16) :: Float64 -163 div0(Float32 NULL, UInt16 NULL) :: Float64 NULL -164 div0(Float32, UInt32) :: Float64 -165 div0(Float32 NULL, UInt32 NULL) :: Float64 NULL -166 div0(Float32, UInt64) :: Float64 -167 div0(Float32 NULL, UInt64 NULL) :: Float64 NULL -168 div0(Float32, Int8) :: Float64 -169 div0(Float32 NULL, Int8 NULL) :: Float64 NULL -170 div0(Float32, Int16) :: Float64 -171 div0(Float32 NULL, Int16 NULL) :: Float64 NULL -172 div0(Float32, Int32) :: Float64 -173 div0(Float32 NULL, Int32 NULL) :: Float64 NULL -174 div0(Float32, Int64) :: Float64 -175 div0(Float32 NULL, Int64 NULL) :: Float64 NULL -176 div0(Float64, UInt8) :: Float64 -177 div0(Float64 NULL, UInt8 NULL) :: Float64 NULL -178 div0(Float64, UInt16) :: Float64 -179 div0(Float64 NULL, UInt16 NULL) :: Float64 NULL -180 div0(Float64, UInt32) :: Float64 -181 div0(Float64 NULL, UInt32 NULL) :: Float64 NULL -182 div0(Float64, UInt64) :: Float64 -183 div0(Float64 NULL, UInt64 NULL) :: Float64 NULL -184 div0(Float64, Int8) :: Float64 -185 div0(Float64 NULL, Int8 NULL) :: Float64 NULL -186 div0(Float64, Int16) :: Float64 -187 div0(Float64 NULL, Int16 NULL) :: Float64 NULL -188 div0(Float64, Int32) :: Float64 -189 div0(Float64 NULL, Int32 NULL) :: Float64 NULL -190 div0(Float64, Int64) :: Float64 -191 div0(Float64 NULL, Int64 NULL) :: Float64 NULL -192 div0(Float32, Float32) :: Float64 -193 div0(Float32 NULL, Float32 NULL) :: Float64 NULL -194 div0(Float32, Float64) :: Float64 -195 div0(Float32 NULL, Float64 NULL) :: Float64 NULL -196 div0(Float64, Float32) :: Float64 -197 div0(Float64 NULL, Float32 NULL) :: Float64 NULL -198 div0(Float64, Float64) :: Float64 -199 div0(Float64 NULL, Float64 NULL) :: Float64 NULL +0 div0(Float64, Float64) :: Float64 +1 div0(Float64 NULL, Float64 NULL) :: Float64 NULL 0 divide FACTORY 1 divide(UInt8, UInt8) :: Float64 2 divide(UInt8 NULL, UInt8 NULL) :: Float64 NULL @@ -1866,106 +1668,7 @@ Functions overloads: 198 divide(Float64 NULL, Float32 NULL) :: Float64 NULL 199 divide(Float64, Float64) :: Float64 200 divide(Float64 NULL, Float64 NULL) :: Float64 NULL -0 divnull(UInt8 NULL, UInt8 NULL) :: Float64 NULL -1 divnull(UInt8 NULL, UInt16 NULL) :: Float64 NULL -2 divnull(UInt8 NULL, UInt32 NULL) :: Float64 NULL -3 divnull(UInt8 NULL, UInt64 NULL) :: Float64 NULL -4 divnull(UInt8 NULL, Int8 NULL) :: Float64 NULL -5 divnull(UInt8 NULL, Int16 NULL) :: Float64 NULL -6 divnull(UInt8 NULL, Int32 NULL) :: Float64 NULL -7 divnull(UInt8 NULL, Int64 NULL) :: Float64 NULL -8 divnull(UInt16 NULL, UInt8 NULL) :: Float64 NULL -9 divnull(UInt16 NULL, UInt16 NULL) :: Float64 NULL -10 divnull(UInt16 NULL, UInt32 NULL) :: Float64 NULL -11 divnull(UInt16 NULL, UInt64 NULL) :: Float64 NULL -12 divnull(UInt16 NULL, Int8 NULL) :: Float64 NULL -13 divnull(UInt16 NULL, Int16 NULL) :: Float64 NULL -14 divnull(UInt16 NULL, Int32 NULL) :: Float64 NULL -15 divnull(UInt16 NULL, Int64 NULL) :: Float64 NULL -16 divnull(UInt32 NULL, UInt8 NULL) :: Float64 NULL -17 divnull(UInt32 NULL, UInt16 NULL) :: Float64 NULL -18 divnull(UInt32 NULL, UInt32 NULL) :: Float64 NULL -19 divnull(UInt32 NULL, UInt64 NULL) :: Float64 NULL -20 divnull(UInt32 NULL, Int8 NULL) :: Float64 NULL -21 divnull(UInt32 NULL, Int16 NULL) :: Float64 NULL -22 divnull(UInt32 NULL, Int32 NULL) :: Float64 NULL -23 divnull(UInt32 NULL, Int64 NULL) :: Float64 NULL -24 divnull(UInt64 NULL, UInt8 NULL) :: Float64 NULL -25 divnull(UInt64 NULL, UInt16 NULL) :: Float64 NULL -26 divnull(UInt64 NULL, UInt32 NULL) :: Float64 NULL -27 divnull(UInt64 NULL, UInt64 NULL) :: Float64 NULL -28 divnull(UInt64 NULL, Int8 NULL) :: Float64 NULL -29 divnull(UInt64 NULL, Int16 NULL) :: Float64 NULL -30 divnull(UInt64 NULL, Int32 NULL) :: Float64 NULL -31 divnull(UInt64 NULL, Int64 NULL) :: Float64 NULL -32 divnull(Int8 NULL, UInt8 NULL) :: Float64 NULL -33 divnull(Int8 NULL, UInt16 NULL) :: Float64 NULL -34 divnull(Int8 NULL, UInt32 NULL) :: Float64 NULL -35 divnull(Int8 NULL, UInt64 NULL) :: Float64 NULL -36 divnull(Int8 NULL, Int8 NULL) :: Float64 NULL -37 divnull(Int8 NULL, Int16 NULL) :: Float64 NULL -38 divnull(Int8 NULL, Int32 NULL) :: Float64 NULL -39 divnull(Int8 NULL, Int64 NULL) :: Float64 NULL -40 divnull(Int16 NULL, UInt8 NULL) :: Float64 NULL -41 divnull(Int16 NULL, UInt16 NULL) :: Float64 NULL -42 divnull(Int16 NULL, UInt32 NULL) :: Float64 NULL -43 divnull(Int16 NULL, UInt64 NULL) :: Float64 NULL -44 divnull(Int16 NULL, Int8 NULL) :: Float64 NULL -45 divnull(Int16 NULL, Int16 NULL) :: Float64 NULL -46 divnull(Int16 NULL, Int32 NULL) :: Float64 NULL -47 divnull(Int16 NULL, Int64 NULL) :: Float64 NULL -48 divnull(Int32 NULL, UInt8 NULL) :: Float64 NULL -49 divnull(Int32 NULL, UInt16 NULL) :: Float64 NULL -50 divnull(Int32 NULL, UInt32 NULL) :: Float64 NULL -51 divnull(Int32 NULL, UInt64 NULL) :: Float64 NULL -52 divnull(Int32 NULL, Int8 NULL) :: Float64 NULL -53 divnull(Int32 NULL, Int16 NULL) :: Float64 NULL -54 divnull(Int32 NULL, Int32 NULL) :: Float64 NULL -55 divnull(Int32 NULL, Int64 NULL) :: Float64 NULL -56 divnull(Int64 NULL, UInt8 NULL) :: Float64 NULL -57 divnull(Int64 NULL, UInt16 NULL) :: Float64 NULL -58 divnull(Int64 NULL, UInt32 NULL) :: Float64 NULL -59 divnull(Int64 NULL, UInt64 NULL) :: Float64 NULL -60 divnull(Int64 NULL, Int8 NULL) :: Float64 NULL -61 divnull(Int64 NULL, Int16 NULL) :: Float64 NULL -62 divnull(Int64 NULL, Int32 NULL) :: Float64 NULL -63 divnull(Int64 NULL, Int64 NULL) :: Float64 NULL -64 divnull(UInt8 NULL, Float32 NULL) :: Float64 NULL -65 divnull(UInt8 NULL, Float64 NULL) :: Float64 NULL -66 divnull(UInt16 NULL, Float32 NULL) :: Float64 NULL -67 divnull(UInt16 NULL, Float64 NULL) :: Float64 NULL -68 divnull(UInt32 NULL, Float32 NULL) :: Float64 NULL -69 divnull(UInt32 NULL, Float64 NULL) :: Float64 NULL -70 divnull(UInt64 NULL, Float32 NULL) :: Float64 NULL -71 divnull(UInt64 NULL, Float64 NULL) :: Float64 NULL -72 divnull(Int8 NULL, Float32 NULL) :: Float64 NULL -73 divnull(Int8 NULL, Float64 NULL) :: Float64 NULL -74 divnull(Int16 NULL, Float32 NULL) :: Float64 NULL -75 divnull(Int16 NULL, Float64 NULL) :: Float64 NULL -76 divnull(Int32 NULL, Float32 NULL) :: Float64 NULL -77 divnull(Int32 NULL, Float64 NULL) :: Float64 NULL -78 divnull(Int64 NULL, Float32 NULL) :: Float64 NULL -79 divnull(Int64 NULL, Float64 NULL) :: Float64 NULL -80 divnull(Float32 NULL, UInt8 NULL) :: Float64 NULL -81 divnull(Float32 NULL, UInt16 NULL) :: Float64 NULL -82 divnull(Float32 NULL, UInt32 NULL) :: Float64 NULL -83 divnull(Float32 NULL, UInt64 NULL) :: Float64 NULL -84 divnull(Float32 NULL, Int8 NULL) :: Float64 NULL -85 divnull(Float32 NULL, Int16 NULL) :: Float64 NULL -86 divnull(Float32 NULL, Int32 NULL) :: Float64 NULL -87 divnull(Float32 NULL, Int64 NULL) :: Float64 NULL -88 divnull(Float64 NULL, UInt8 NULL) :: Float64 NULL -89 divnull(Float64 NULL, UInt16 NULL) :: Float64 NULL -90 divnull(Float64 NULL, UInt32 NULL) :: Float64 NULL -91 divnull(Float64 NULL, UInt64 NULL) :: Float64 NULL -92 divnull(Float64 NULL, Int8 NULL) :: Float64 NULL -93 divnull(Float64 NULL, Int16 NULL) :: Float64 NULL -94 divnull(Float64 NULL, Int32 NULL) :: Float64 NULL -95 divnull(Float64 NULL, Int64 NULL) :: Float64 NULL -96 divnull(Float32 NULL, Float32 NULL) :: Float64 NULL -97 divnull(Float32 NULL, Float64 NULL) :: Float64 NULL -98 divnull(Float64 NULL, Float32 NULL) :: Float64 NULL -99 divnull(Float64 NULL, Float64 NULL) :: Float64 NULL +0 divnull(Float64 NULL, Float64 NULL) :: Float64 NULL 0 epoch(Int64) :: Interval 1 epoch(Int64 NULL) :: Interval NULL 0 eq(Variant, Variant) :: Boolean