diff --git a/src/common/io/src/decimal.rs b/src/common/io/src/decimal.rs index 195b2e54b5bd3..ab0b03d6b2286 100644 --- a/src/common/io/src/decimal.rs +++ b/src/common/io/src/decimal.rs @@ -12,65 +12,86 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::fmt::Write; +use std::fmt::Debug; +use std::fmt::Display; +use std::fmt::Formatter; +use std::fmt::Result; use ethnum::i256; -pub fn display_decimal_128(num: i128, scale: u8) -> String { - let mut buf = String::new(); - if scale == 0 { - write!(buf, "{}", num).unwrap(); - } else { - let pow_scale = 10_i128.pow(scale as u32); - if num >= 0 { - write!( - buf, - "{}.{:0>width$}", - num / pow_scale, - (num % pow_scale).abs(), - width = scale as usize - ) - .unwrap(); - } else { - write!( - buf, - "-{}.{:0>width$}", - -num / pow_scale, - (num % pow_scale).abs(), - width = scale as usize - ) - .unwrap(); +pub fn display_decimal_128(num: i128, scale: u8) -> impl Display + Debug { + struct Decimal { + num: i128, + scale: u8, + } + + impl Display for Decimal { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + if self.scale == 0 { + write!(f, "{}", self.num) + } else { + let pow_scale = 10_i128.pow(self.scale as u32); + let sign = if self.num.is_negative() { "-" } else { "" }; + let num = self.num.abs(); + write!( + f, + "{sign}{}.{:0>width$}", + num / pow_scale, + num % pow_scale, + width = self.scale as usize + ) + } + } + } + + impl Debug for Decimal { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.write_str(&self.to_string()) } } - buf + + Decimal { num, scale } } -pub fn display_decimal_256(num: i256, scale: u8) -> String { - let mut buf = String::new(); - if scale == 0 { - write!(buf, "{}", num).unwrap(); - } else { - let pow_scale = i256::from(10).pow(scale as u32); - // -1/10 = 0 - if num >= 0 { - write!( - buf, - "{}.{:0>width$}", - num / pow_scale, - (num % pow_scale).abs(), - width = scale as usize - ) - .unwrap(); - } else { - write!( - buf, - "-{}.{:0>width$}", - -num / pow_scale, - (num % pow_scale).abs(), - width = scale as usize - ) - .unwrap(); +pub fn display_decimal_256(num: i256, scale: u8) -> impl Display + Debug { + struct Decimal256 { + num: i256, + scale: u8, + } + + impl Display for Decimal256 { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + if self.scale == 0 { + write!(f, "{}", self.num) + } else { + let pow_scale = i256::from(10).pow(self.scale as u32); + // -1/10 = 0 + if self.num >= 0 { + write!( + f, + "{}.{:0>width$}", + self.num / pow_scale, + (self.num % pow_scale).abs(), + width = self.scale as usize + ) + } else { + write!( + f, + "-{}.{:0>width$}", + -self.num / pow_scale, + (self.num % pow_scale).abs(), + width = self.scale as usize + ) + } + } + } + } + + impl Debug for Decimal256 { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.write_str(&self.to_string()) } } - buf + + Decimal256 { num, scale } } diff --git a/src/common/native/src/read/array/double.rs b/src/common/native/src/read/array/double.rs index f17bebee050da..2838e675c92ee 100644 --- a/src/common/native/src/read/array/double.rs +++ b/src/common/native/src/read/array/double.rs @@ -17,9 +17,9 @@ use std::io::Cursor; use std::marker::PhantomData; use databend_common_column::buffer::Buffer; -use databend_common_expression::types::AccessType; use databend_common_expression::types::Number; use databend_common_expression::types::NumberType; +use databend_common_expression::types::ValueType; use databend_common_expression::Column; use databend_common_expression::TableDataType; diff --git a/src/common/native/src/read/array/interval.rs b/src/common/native/src/read/array/interval.rs index 2738c72669794..efa01b25b0a75 100644 --- a/src/common/native/src/read/array/interval.rs +++ b/src/common/native/src/read/array/interval.rs @@ -16,8 +16,8 @@ use std::io::Cursor; use databend_common_column::buffer::Buffer; use databend_common_column::types::months_days_micros; -use databend_common_expression::types::AccessType; use databend_common_expression::types::IntervalType; +use databend_common_expression::types::ValueType; use databend_common_expression::Column; use databend_common_expression::TableDataType; diff --git a/src/meta/proto-conv/src/schema_from_to_protobuf_impl.rs b/src/meta/proto-conv/src/schema_from_to_protobuf_impl.rs index 8aee04c2f69e8..4896469d9b1aa 100644 --- a/src/meta/proto-conv/src/schema_from_to_protobuf_impl.rs +++ b/src/meta/proto-conv/src/schema_from_to_protobuf_impl.rs @@ -420,6 +420,9 @@ impl FromToProto for ex::types::DecimalDataType { fn to_pb(&self) -> Result { let x = match self { + ex::types::DecimalDataType::Decimal64(x) => { + pb::decimal::Decimal::Decimal128(ex::types::decimal::DecimalSize::to_pb(x)?) + } ex::types::DecimalDataType::Decimal128(x) => { pb::decimal::Decimal::Decimal128(ex::types::decimal::DecimalSize::to_pb(x)?) } diff --git a/src/query/ast/src/ast/common.rs b/src/query/ast/src/ast/common.rs index a086f54f9cf2b..e8d99464acc91 100644 --- a/src/query/ast/src/ast/common.rs +++ b/src/query/ast/src/ast/common.rs @@ -14,7 +14,6 @@ use std::fmt::Display; use std::fmt::Formatter; -use std::fmt::Write as _; use derive_visitor::Drive; use derive_visitor::DriveMut; @@ -291,32 +290,39 @@ pub(crate) fn write_space_separated_string_map( Ok(()) } -pub fn display_decimal_256(num: i256, scale: u8) -> String { - let mut buf = String::new(); - if scale == 0 { - write!(buf, "{}", num).unwrap(); - } else { - let pow_scale = i256::from(10).pow(scale as u32); - // -1/10 = 0 - if num >= 0 { - write!( - buf, - "{}.{:0>width$}", - num / pow_scale, - (num % pow_scale).abs(), - width = scale as usize - ) - .unwrap(); - } else { - write!( - buf, - "-{}.{:0>width$}", - -num / pow_scale, - (num % pow_scale).abs(), - width = scale as usize - ) - .unwrap(); +pub(crate) fn display_decimal_256(num: i256, scale: u8) -> impl Display { + struct Decimal256 { + num: i256, + scale: u8, + } + + impl Display for Decimal256 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.scale == 0 { + write!(f, "{}", self.num) + } else { + let pow_scale = i256::from(10).pow(self.scale as u32); + // -1/10 = 0 + if self.num >= 0 { + write!( + f, + "{}.{:0>width$}", + self.num / pow_scale, + (self.num % pow_scale).abs(), + width = self.scale as usize + ) + } else { + write!( + f, + "-{}.{:0>width$}", + -self.num / pow_scale, + (self.num % pow_scale).abs(), + width = self.scale as usize + ) + } + } } } - buf + + Decimal256 { num, scale } } diff --git a/src/query/expression/src/aggregate/group_hash.rs b/src/query/expression/src/aggregate/group_hash.rs index 4f662e51e6b23..b3d6e2a3f4131 100644 --- a/src/query/expression/src/aggregate/group_hash.rs +++ b/src/query/expression/src/aggregate/group_hash.rs @@ -21,12 +21,14 @@ use databend_common_exception::Result; use crate::types::i256; use crate::types::number::Number; +use crate::types::AccessType; use crate::types::AnyType; use crate::types::BinaryColumn; use crate::types::BinaryType; use crate::types::BitmapType; use crate::types::BooleanType; use crate::types::DateType; +use crate::types::Decimal64As128Type; use crate::types::DecimalColumn; use crate::types::DecimalScalar; use crate::types::DecimalType; @@ -100,6 +102,9 @@ impl ValueVisitor for HashVisitor<'_, IS_FIRST> { fn visit_any_decimal(&mut self, column: DecimalColumn) -> Result<()> { match column { + DecimalColumn::Decimal64(buffer, _) => { + self.combine_group_hash_type_column::(&buffer); + } DecimalColumn::Decimal128(buffer, _) => { self.combine_group_hash_type_column::>(&buffer); } @@ -198,7 +203,7 @@ impl ValueVisitor for HashVisitor<'_, IS_FIRST> { impl HashVisitor<'_, IS_FIRST> { fn combine_group_hash_type_column(&mut self, col: &T::Column) where - T: ValueType, + T: AccessType, for<'a> T::ScalarRef<'a>: AggHash, { if IS_FIRST { @@ -270,6 +275,7 @@ where I: Index NumberScalar::NUM_TYPE(v) => v.agg_hash(), }), Scalar::Decimal(v) => match v { + DecimalScalar::Decimal64(v, _) => (v as i128).agg_hash(), DecimalScalar::Decimal128(v, _) => v.agg_hash(), DecimalScalar::Decimal256(v, _) => v.agg_hash(), }, @@ -539,7 +545,6 @@ mod tests { use databend_common_column::bitmap::Bitmap; use super::*; - use crate::types::AccessType; use crate::types::ArgType; use crate::types::Int32Type; use crate::types::NullableColumn; diff --git a/src/query/expression/src/aggregate/payload_row.rs b/src/query/expression/src/aggregate/payload_row.rs index 8cd613c7f4a75..9cd0b2b16b6fb 100644 --- a/src/query/expression/src/aggregate/payload_row.rs +++ b/src/query/expression/src/aggregate/payload_row.rs @@ -90,6 +90,7 @@ pub unsafe fn serialize_column_to_rowformat( } }), Column::Decimal(v) => match v { + DecimalColumn::Decimal64(_, _) => unimplemented!(), DecimalColumn::Decimal128(buffer, size) => { if size.can_carried_by_128() { for index in select_vector.iter().take(rows).copied() { @@ -264,6 +265,7 @@ pub unsafe fn row_match_column( } }), Column::Decimal(v) => match v { + DecimalColumn::Decimal64(_, _) => unreachable!(), DecimalColumn::Decimal128(_, _) => row_match_column_type::>( col, validity, diff --git a/src/query/expression/src/converts/arrow/to.rs b/src/query/expression/src/converts/arrow/to.rs index 55dbf561e4a20..0ddb4ead26156 100644 --- a/src/query/expression/src/converts/arrow/to.rs +++ b/src/query/expression/src/converts/arrow/to.rs @@ -113,6 +113,9 @@ impl From<&TableField> for Field { TableDataType::Number(ty) => with_number_type!(|TYPE| match ty { NumberDataType::TYPE => ArrowDataType::TYPE, }), + TableDataType::Decimal(DecimalDataType::Decimal64(size)) => { + ArrowDataType::Decimal128(size.precision(), size.scale() as i8) + } TableDataType::Decimal(DecimalDataType::Decimal128(size)) => { ArrowDataType::Decimal128(size.precision(), size.scale() as i8) } @@ -315,7 +318,7 @@ impl From<&Column> for ArrayData { Column::Decimal(c) => { let c = c.clone().strict_decimal_data_type(); let arrow_type = match c { - DecimalColumn::Decimal128(_, size) => { + DecimalColumn::Decimal64(_, size) | DecimalColumn::Decimal128(_, size) => { ArrowDataType::Decimal128(size.precision(), size.scale() as _) } DecimalColumn::Decimal256(_, size) => { diff --git a/src/query/expression/src/evaluator.rs b/src/query/expression/src/evaluator.rs index 875b39712c39a..cf4a0e939e4a4 100644 --- a/src/query/expression/src/evaluator.rs +++ b/src/query/expression/src/evaluator.rs @@ -82,12 +82,12 @@ impl Default for EvaluateOptions<'_> { } impl<'a> EvaluateOptions<'a> { - pub fn new(selection: Option<&'a [u32]>) -> EvaluateOptions<'a> { + pub fn new_for_select(selection: Option<&'a [u32]>) -> EvaluateOptions<'a> { Self { selection, suppress_error: false, errors: None, - strict_eval: true, + strict_eval: false, } } @@ -149,18 +149,25 @@ impl<'a> Evaluator<'a> { pub fn run(&self, expr: &Expr) -> Result> { self.partial_run(expr, None, &mut EvaluateOptions::default()) - .map_err(|err| { - let expr_str = format!("`{}`", expr.sql_display()); - if err.message().contains(expr_str.as_str()) { - err - } else { - ErrorCode::BadArguments(format!( - "{}, during run expr: {expr_str}", - err.message() - )) - .set_span(err.span()) - } - }) + .map_err(|err| Self::map_err(err, expr)) + } + + pub fn run_fast(&self, expr: &Expr) -> Result> { + self.partial_run(expr, None, &mut EvaluateOptions { + strict_eval: false, + ..Default::default() + }) + .map_err(|err| Self::map_err(err, expr)) + } + + fn map_err(err: ErrorCode, expr: &Expr) -> ErrorCode { + let expr_str = format!("`{}`", expr.sql_display()); + if err.message().contains(expr_str.as_str()) { + err + } else { + ErrorCode::BadArguments(format!("{}, during run expr: {expr_str}", err.message())) + .set_span(err.span()) + } } /// Run an expression partially, only the rows that are valid in the validity bitmap @@ -259,11 +266,11 @@ impl<'a> Evaluator<'a> { Value::Column(col) => assert_eq!(&col.data_type(), expr.data_type()), } - if !expr.is_column_ref() && options.strict_eval { + if !expr.is_column_ref() && !expr.is_constant() && options.strict_eval { let mut check = CheckStrictValue; assert!( check.visit_value(result.clone()).is_ok(), - "result {result:?}", + "strict check fail on expr: {expr}", ) } @@ -287,6 +294,9 @@ impl<'a> Evaluator<'a> { } = call; let child_suppress_error = function.signature.name == "is_not_error"; let mut child_option = options.with_suppress_error(child_suppress_error); + if child_option.strict_eval && call.generics.is_empty() { + child_option.strict_eval = false; + } let args = args .iter() @@ -2233,9 +2243,7 @@ impl<'a, Index: ColumnIndex> ConstantFolder<'a, Index> { }); let (calc_domain, eval) = match &function.eval { - FunctionEval::Scalar { - calc_domain, eval, .. - } => (calc_domain, eval), + FunctionEval::Scalar { calc_domain, eval } => (calc_domain, eval), FunctionEval::SRF { .. } => { return (func_expr, None); } diff --git a/src/query/expression/src/filter/select.rs b/src/query/expression/src/filter/select.rs index fa8210a4980f9..0eeacfdf55656 100644 --- a/src/query/expression/src/filter/select.rs +++ b/src/query/expression/src/filter/select.rs @@ -25,9 +25,15 @@ use crate::types::BooleanType; use crate::types::DataType; use crate::types::DateType; use crate::types::Decimal128As256Type; +use crate::types::Decimal128As64Type; use crate::types::Decimal128Type; use crate::types::Decimal256As128Type; +use crate::types::Decimal256As64Type; use crate::types::Decimal256Type; +use crate::types::Decimal64As128Type; +use crate::types::Decimal64As256Type; +use crate::types::Decimal64Type; +use crate::types::DecimalDataKind; use crate::types::DecimalDataType; use crate::types::EmptyArrayType; use crate::types::NullableType; @@ -36,8 +42,6 @@ use crate::types::StringType; use crate::types::TimestampType; use crate::types::VariantType; use crate::with_number_mapped_type; -use crate::Column; -use crate::LikePattern; use crate::Selector; use crate::Value; @@ -94,44 +98,7 @@ impl Selector<'_> { } DataType::Decimal(_) => { - let (left_type, _) = DecimalDataType::from_value(&left).unwrap(); - let (right_type, _) = DecimalDataType::from_value(&right).unwrap(); - debug_assert_eq!(left_type.size(), right_type.size()); - - match (left_type, right_type) { - (DecimalDataType::Decimal128(_), DecimalDataType::Decimal128(_)) => { - self.select_type_values_cmp::( - &op, left, right, validity, buffers, has_false, - ) - } - (DecimalDataType::Decimal256(_), DecimalDataType::Decimal256(_)) => { - self.select_type_values_cmp::( - &op, left, right, validity, buffers, has_false, - ) - } - (DecimalDataType::Decimal128(size), DecimalDataType::Decimal256(_)) => { - if size.can_carried_by_128() { - self.select_type_values_cmp_lr::( - &op, left, right, validity, buffers, has_false, - ) - } else { - self.select_type_values_cmp_lr::( - &op, left, right, validity, buffers, has_false, - ) - } - } - (DecimalDataType::Decimal256(size), DecimalDataType::Decimal128(_)) => { - if size.can_carried_by_128() { - self.select_type_values_cmp_lr::( - &op, left, right, validity, buffers, has_false, - ) - } else { - self.select_type_values_cmp_lr::( - &op, left, right, validity, buffers, has_false, - ) - } - } - } + self.select_values_decimal(&op, left, right, buffers, has_false, validity) } DataType::Date => self .select_type_values_cmp::(&op, left, right, validity, buffers, has_false), @@ -155,6 +122,114 @@ impl Selector<'_> { } } + fn select_values_decimal( + &self, + op: &SelectOp, + left: Value, + right: Value, + buffers: SelectionBuffers<'_>, + has_false: bool, + validity: Option, + ) -> std::result::Result { + let (left_type, _) = DecimalDataType::from_value(&left).unwrap(); + let (right_type, _) = DecimalDataType::from_value(&right).unwrap(); + debug_assert_eq!(left_type.size(), right_type.size()); + + match (left_type, right_type) { + (DecimalDataType::Decimal64(_), DecimalDataType::Decimal64(_)) => self + .select_type_values_cmp::( + op, left, right, validity, buffers, has_false, + ), + (DecimalDataType::Decimal128(_), DecimalDataType::Decimal128(_)) => self + .select_type_values_cmp::( + op, left, right, validity, buffers, has_false, + ), + (DecimalDataType::Decimal256(_), DecimalDataType::Decimal256(_)) => self + .select_type_values_cmp::( + op, left, right, validity, buffers, has_false, + ), + + (DecimalDataType::Decimal64(size), DecimalDataType::Decimal128(_)) => { + match size.data_kind() { + DecimalDataKind::Decimal64 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + + DecimalDataKind::Decimal128 | DecimalDataKind::Decimal256 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + } + } + (DecimalDataType::Decimal128(size), DecimalDataType::Decimal64(_)) => { + match size.data_kind() { + DecimalDataKind::Decimal64 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + + DecimalDataKind::Decimal128 | DecimalDataKind::Decimal256 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + } + } + + (DecimalDataType::Decimal64(size), DecimalDataType::Decimal256(_)) => { + match size.data_kind() { + DecimalDataKind::Decimal64 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + + DecimalDataKind::Decimal128 | DecimalDataKind::Decimal256 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + } + } + (DecimalDataType::Decimal256(size), DecimalDataType::Decimal64(_)) => { + match size.data_kind() { + DecimalDataKind::Decimal64 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + + DecimalDataKind::Decimal128 | DecimalDataKind::Decimal256 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + } + } + + (DecimalDataType::Decimal128(size), DecimalDataType::Decimal256(_)) => { + match size.data_kind() { + DecimalDataKind::Decimal64 | DecimalDataKind::Decimal128 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + DecimalDataKind::Decimal256 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + } + } + (DecimalDataType::Decimal256(size), DecimalDataType::Decimal128(_)) => { + match size.data_kind() { + DecimalDataKind::Decimal64 | DecimalDataKind::Decimal128 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + DecimalDataKind::Decimal256 => self + .select_type_values_cmp_lr::( + op, left, right, validity, buffers, has_false, + ), + } + } + } + } + // Select indices by single `Value`. pub(super) fn select_value( &self, @@ -203,25 +278,4 @@ impl Selector<'_> { }; Ok(count) } - - pub(super) fn select_like( - &self, - mut column: Column, - data_type: &DataType, - like_pattern: &LikePattern, - not: bool, - buffers: SelectionBuffers, - has_false: bool, - ) -> Result { - // Remove `NullableColumn` and get the inner column and validity. - let mut validity = None; - if let DataType::Nullable(_) = data_type { - let nullable_column = column.clone().into_nullable().unwrap(); - column = nullable_column.column; - validity = Some(nullable_column.validity); - } - // It's safe to unwrap because the column's data type is `DataType::String`. - let column = column.into_string().unwrap(); - self.select_like_adapt(column, like_pattern, not, validity, buffers, has_false) - } } diff --git a/src/query/expression/src/filter/select_value/mod.rs b/src/query/expression/src/filter/select_value/mod.rs index 2da3d960bc9ed..d0b811a40bb51 100644 --- a/src/query/expression/src/filter/select_value/mod.rs +++ b/src/query/expression/src/filter/select_value/mod.rs @@ -161,7 +161,7 @@ impl Selector<'_> { } } - pub(super) fn select_like_adapt( + pub(super) fn select_like( &self, column: StringColumn, like_pattern: &LikePattern, diff --git a/src/query/expression/src/filter/selector.rs b/src/query/expression/src/filter/selector.rs index d777595288abc..e76a66bbfaa59 100644 --- a/src/query/expression/src/filter/selector.rs +++ b/src/query/expression/src/filter/selector.rs @@ -25,6 +25,7 @@ use crate::filter::SelectExpr; use crate::filter::SelectOp; use crate::types::AnyType; use crate::types::DataType; +use crate::Column; use crate::EvalContext; use crate::EvaluateOptions; use crate::Evaluator; @@ -305,7 +306,7 @@ impl<'a> Selector<'a> { *mutable_false_idx + count, &select_strategy, ); - let mut eval_options = EvaluateOptions::new(selection); + let mut eval_options = EvaluateOptions::new_for_select(selection); let children = self.evaluator.get_children(exprs, &mut eval_options)?; let (left_value, left_data_type) = children[0].clone(); let (right_value, right_data_type) = children[1].clone(); @@ -354,37 +355,46 @@ impl<'a> Selector<'a> { *mutable_false_idx + count, &select_strategy, ); - let mut eval_options = EvaluateOptions::new(selection); + let mut eval_options = EvaluateOptions::new_for_select(selection); let (value, data_type) = self .evaluator .get_select_child(column_ref, &mut eval_options)?; debug_assert!( matches!(data_type, DataType::String | DataType::Nullable(box DataType::String)) ); - match value { - Value::Scalar(Scalar::Null) => Ok(0), - _ => match value.into_column() { - Ok(column) => self.select_like( - column, - &data_type, - like_pattern, - not, - SelectionBuffers { - true_selection, - false_selection: false_selection.0, - mutable_true_idx, - mutable_false_idx, - select_strategy, - count, - }, - false_selection.1, - ), - Err(e) => Err(ErrorCode::Internal(format!( - "Can not convert to column with error: {}", - e - ))), - }, + + if value.is_scalar_null() { + return Ok(0); } + let column = value + .into_column() + .map_err(|v| ErrorCode::Internal(format!("Can not convert to column: {v}")))?; + + // Extract StringColumn and validity from Column + let (column, validity) = match column.into_nullable() { + Ok(nullable) => ( + nullable.column.into_string().unwrap(), + Some(nullable.validity), + ), + Err(Column::String(column)) => (column, None), + _ => unreachable!(), + }; + + self.select_like( + column, + like_pattern, + not, + validity, + SelectionBuffers { + true_selection, + false_selection: false_selection.0, + mutable_true_idx, + mutable_false_idx, + select_strategy, + count, + }, + false_selection.1, + ) } // Process SelectExpr::Others. @@ -458,7 +468,7 @@ impl<'a> Selector<'a> { generics, .. }) if function.signature.name == "if" => { - let mut eval_options = EvaluateOptions::new(selection); + let mut eval_options = EvaluateOptions::new_for_select(selection); let result = self .evaluator @@ -483,7 +493,7 @@ impl<'a> Selector<'a> { expr.sql_display(), return_type ); - let mut eval_options = EvaluateOptions::new(selection) + let mut eval_options = EvaluateOptions::new_for_select(selection) .with_suppress_error(function.signature.name == "is_not_error"); let args = args @@ -537,7 +547,7 @@ impl<'a> Selector<'a> { *mutable_false_idx + count, &select_strategy, ); - let mut eval_options = EvaluateOptions::new(selection); + let mut eval_options = EvaluateOptions::new_for_select(selection); let value = self.evaluator.get_select_child(expr, &mut eval_options)?.0; let src_type = expr.data_type(); let result = if *is_try { @@ -570,7 +580,7 @@ impl<'a> Selector<'a> { *mutable_false_idx + count, &select_strategy, ); - let mut eval_options = EvaluateOptions::new(selection); + let mut eval_options = EvaluateOptions::new_for_select(selection); let data_types = args.iter().map(|arg| arg.data_type().clone()).collect(); let args = args diff --git a/src/query/expression/src/function.rs b/src/query/expression/src/function.rs index deaab90040a29..4f2f3efd3eff6 100755 --- a/src/query/expression/src/function.rs +++ b/src/query/expression/src/function.rs @@ -154,7 +154,7 @@ pub enum FunctionEval { }, } -#[derive(Clone, Debug)] +#[derive(Debug, Clone, PartialEq)] pub struct FunctionContext { pub tz: TimeZone, pub now: Zoned, @@ -200,7 +200,7 @@ impl Default for FunctionContext { } } -#[derive(Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct EvalContext<'a> { pub generics: &'a GenericMap, pub num_rows: usize, diff --git a/src/query/expression/src/kernels/group_by_hash/method_fixed_keys.rs b/src/query/expression/src/kernels/group_by_hash/method_fixed_keys.rs index 68ebd0f52c84f..beedd1135b7ab 100644 --- a/src/query/expression/src/kernels/group_by_hash/method_fixed_keys.rs +++ b/src/query/expression/src/kernels/group_by_hash/method_fixed_keys.rs @@ -22,7 +22,6 @@ use databend_common_exception::ErrorCode; use databend_common_exception::Result; use databend_common_hashtable::FastHash; use ethnum::u256; -use ethnum::U256; use micromarshal::Marshal; use crate::types::boolean::BooleanType; @@ -40,6 +39,7 @@ use crate::types::Decimal256As128Type; use crate::types::Decimal256Type; use crate::types::NumberDataType; use crate::types::NumberType; +use crate::types::ValueType; use crate::with_integer_mapped_type; use crate::with_number_mapped_type; use crate::Column; @@ -363,7 +363,7 @@ macro_rules! impl_hash_method_fixed_large_keys { } impl_hash_method_fixed_large_keys! {u128, U128} -impl_hash_method_fixed_large_keys! {U256, U256} +impl_hash_method_fixed_large_keys! {u256, U256} // Group by (nullable(u16), nullable(u8)) needs 2 + 1 + 1 + 1 = 5 bytes, then we pad the bytes up to u64 to store the hash value. // If the value is null, we write 1 to the null_offset, otherwise we write 0. diff --git a/src/query/expression/src/property.rs b/src/query/expression/src/property.rs index d4473e3ca0a29..aec4341d071d0 100644 --- a/src/query/expression/src/property.rs +++ b/src/query/expression/src/property.rs @@ -27,6 +27,7 @@ use crate::types::number::SimpleDomain; use crate::types::number::F32; use crate::types::number::F64; use crate::types::string::StringDomain; +use crate::types::AccessType; use crate::types::AnyType; use crate::types::ArgType; use crate::types::BooleanType; @@ -37,7 +38,6 @@ use crate::types::NumberDataType; use crate::types::NumberType; use crate::types::StringType; use crate::types::TimestampType; -use crate::types::ValueType; use crate::with_decimal_type; use crate::with_number_type; use crate::ColumnBuilder; @@ -97,7 +97,7 @@ pub enum FunctionKind { /// Describe the behavior of a function to eliminate the runtime /// evaluation of the function if possible. #[derive(Debug, Clone, PartialEq, EnumAsInner)] -pub enum FunctionDomain { +pub enum FunctionDomain { /// The function may return error. MayThrow, /// The function must not return error, and the return value can be @@ -130,8 +130,8 @@ pub enum Domain { Undefined, } -impl FunctionDomain { - pub fn map(self, f: impl Fn(T::Domain) -> U::Domain) -> FunctionDomain { +impl FunctionDomain { + pub fn map(self, f: impl Fn(T::Domain) -> U::Domain) -> FunctionDomain { match self { FunctionDomain::MayThrow => FunctionDomain::MayThrow, FunctionDomain::Full => FunctionDomain::Full, @@ -198,12 +198,12 @@ impl Domain { DataType::Decimal(size) => { if size.can_carried_by_128() { Domain::Decimal(DecimalDomain::Decimal128( - Decimal128Type::full_domain(), + Decimal128Type::full_domain(size), *size, )) } else { Domain::Decimal(DecimalDomain::Decimal256( - Decimal256Type::full_domain(), + Decimal256Type::full_domain(size), *size, )) } @@ -487,14 +487,20 @@ impl Domain { Scalar::Number(NumberScalar::Float64(*min)), Scalar::Number(NumberScalar::Float64(*max)), ), - Domain::Decimal(DecimalDomain::Decimal128(SimpleDomain { min, max }, sz)) => ( - Scalar::Decimal(DecimalScalar::Decimal128(*min, *sz)), - Scalar::Decimal(DecimalScalar::Decimal128(*max, *sz)), - ), - Domain::Decimal(DecimalDomain::Decimal256(SimpleDomain { min, max }, sz)) => ( - Scalar::Decimal(DecimalScalar::Decimal256(*min, *sz)), - Scalar::Decimal(DecimalScalar::Decimal256(*max, *sz)), - ), + Domain::Decimal(decimal_domain) => match decimal_domain { + DecimalDomain::Decimal64(SimpleDomain { min, max }, size) => ( + Scalar::Decimal(DecimalScalar::Decimal64(*min, *size)), + Scalar::Decimal(DecimalScalar::Decimal64(*max, *size)), + ), + DecimalDomain::Decimal128(SimpleDomain { min, max }, size) => ( + Scalar::Decimal(DecimalScalar::Decimal128(*min, *size)), + Scalar::Decimal(DecimalScalar::Decimal128(*max, *size)), + ), + DecimalDomain::Decimal256(SimpleDomain { min, max }, size) => ( + Scalar::Decimal(DecimalScalar::Decimal256(*min, *size)), + Scalar::Decimal(DecimalScalar::Decimal256(*max, *size)), + ), + }, Domain::Boolean(BooleanDomain { has_false, has_true, @@ -561,7 +567,7 @@ const ALL_FALSE_DOMAIN: BooleanDomain = BooleanDomain { has_false: true, }; -impl SimpleDomainCmp for SimpleDomain { +impl SimpleDomainCmp for SimpleDomain { fn domain_eq(&self, other: &Self) -> FunctionDomain { if self.min > other.max || self.max < other.min { FunctionDomain::Domain(ALL_FALSE_DOMAIN) diff --git a/src/query/expression/src/row/row_converter.rs b/src/query/expression/src/row/row_converter.rs index 275abb3e464f3..9163fc9e84475 100644 --- a/src/query/expression/src/row/row_converter.rs +++ b/src/query/expression/src/row/row_converter.rs @@ -28,7 +28,12 @@ use crate::types::i256; use crate::types::AccessType; use crate::types::DataType; use crate::types::Decimal128As256Type; +use crate::types::Decimal128As64Type; use crate::types::Decimal256As128Type; +use crate::types::Decimal256As64Type; +use crate::types::Decimal64As128Type; +use crate::types::Decimal64As256Type; +use crate::types::DecimalDataKind; use crate::types::NumberColumn; use crate::types::NumberDataType; use crate::with_number_mapped_type; @@ -77,7 +82,7 @@ impl RowConverter { /// Convert columns into [`BinaryColumn`] represented comparable row format. pub fn convert_columns(&self, columns: &[Column], num_rows: usize) -> BinaryColumn { - debug_assert!(columns.len() == self.fields.len()); + debug_assert_eq!(columns.len(), self.fields.len()); debug_assert!(columns .iter() .zip(self.fields.iter()) @@ -106,13 +111,17 @@ impl RowConverter { lengths.iter_mut().for_each(|x| *x += NUM_TYPE::ENCODED_LEN) } }), - DataType::Decimal(size) => { - if size.can_carried_by_128() { + DataType::Decimal(size) => match size.data_kind() { + DecimalDataKind::Decimal64 => { + lengths.iter_mut().for_each(|x| *x += i64::ENCODED_LEN) + } + DecimalDataKind::Decimal128 => { lengths.iter_mut().for_each(|x| *x += i128::ENCODED_LEN) - } else { + } + DecimalDataKind::Decimal256 => { lengths.iter_mut().for_each(|x| *x += i256::ENCODED_LEN) } - } + }, DataType::Timestamp => lengths.iter_mut().for_each(|x| *x += i64::ENCODED_LEN), DataType::Interval => lengths .iter_mut() @@ -245,22 +254,45 @@ fn encode_column(out: &mut BinaryColumnBuilder, column: &Column, asc: bool, null }) } Column::Decimal(col) => match col { - DecimalColumn::Decimal128(buffer, size) => { - if size.can_carried_by_128() { + DecimalColumn::Decimal64(buffer, size) => match size.data_kind() { + DecimalDataKind::Decimal64 => { + fixed::encode(out, buffer, validity, asc, nulls_first) + } + DecimalDataKind::Decimal128 => { + let iter = Decimal64As128Type::iter_column(&buffer); + fixed::encode(out, iter, validity, asc, nulls_first) + } + DecimalDataKind::Decimal256 => { + let iter = Decimal64As256Type::iter_column(&buffer); + fixed::encode(out, iter, validity, asc, nulls_first) + } + }, + DecimalColumn::Decimal128(buffer, size) => match size.data_kind() { + DecimalDataKind::Decimal64 => { + let iter = Decimal128As64Type::iter_column(&buffer); + fixed::encode(out, iter, validity, asc, nulls_first) + } + DecimalDataKind::Decimal128 => { fixed::encode(out, buffer, validity, asc, nulls_first) - } else { + } + DecimalDataKind::Decimal256 => { let iter = Decimal128As256Type::iter_column(&buffer); fixed::encode(out, iter, validity, asc, nulls_first) } - } - DecimalColumn::Decimal256(buffer, size) => { - if size.can_carried_by_128() { + }, + DecimalColumn::Decimal256(buffer, size) => match size.data_kind() { + DecimalDataKind::Decimal64 => { + let iter = Decimal256As64Type::iter_column(&buffer); + fixed::encode(out, iter, validity, asc, nulls_first) + } + DecimalDataKind::Decimal128 => { let iter = Decimal256As128Type::iter_column(&buffer); fixed::encode(out, iter, validity, asc, nulls_first) - } else { + } + DecimalDataKind::Decimal256 => { fixed::encode(out, buffer, validity, asc, nulls_first) } - } + }, }, Column::Timestamp(col) => fixed::encode(out, col, validity, asc, nulls_first), Column::Interval(col) => fixed::encode(out, col, validity, asc, nulls_first), diff --git a/src/query/expression/src/type_check.rs b/src/query/expression/src/type_check.rs index b5968effa6887..bf1ee8bfa63c6 100755 --- a/src/query/expression/src/type_check.rs +++ b/src/query/expression/src/type_check.rs @@ -31,7 +31,6 @@ use crate::types::decimal::DecimalSize; use crate::types::decimal::MAX_DECIMAL128_PRECISION; use crate::types::decimal::MAX_DECIMAL256_PRECISION; use crate::types::DataType; -use crate::types::DecimalDataType; use crate::types::Number; use crate::visit_expr; use crate::AutoCastRules; @@ -715,20 +714,14 @@ pub fn common_super_type( | (DataType::Decimal(a), DataType::Number(num_ty)) if !num_ty.is_float() => { - let b = DecimalDataType::from_size(num_ty.get_decimal_properties().unwrap()).unwrap(); + let b = num_ty.get_decimal_properties().unwrap(); let scale = a.scale().max(b.scale()); - let mut precision = a.leading_digits().max(b.leading_digits()) + scale; + let precision = a.leading_digits().max(b.leading_digits()) + scale; - if a.precision() <= MAX_DECIMAL128_PRECISION - && b.precision() <= MAX_DECIMAL128_PRECISION - { - precision = precision.min(MAX_DECIMAL128_PRECISION); - } else { - precision = precision.min(MAX_DECIMAL256_PRECISION); - } - - Some(DataType::Decimal(DecimalSize::new(precision, scale).ok()?)) + Some(DataType::Decimal( + DecimalSize::new(precision.min(MAX_DECIMAL256_PRECISION), scale).ok()?, + )) } (DataType::Number(num_ty), DataType::Decimal(_)) | (DataType::Decimal(_), DataType::Number(num_ty)) diff --git a/src/query/expression/src/types.rs b/src/query/expression/src/types.rs index 31fb037d81a8d..7da236ad5eeda 100755 --- a/src/query/expression/src/types.rs +++ b/src/query/expression/src/types.rs @@ -371,6 +371,7 @@ impl DataType { } } +/// AccessType defines a series of access methods for a data type pub trait AccessType: Debug + Clone + PartialEq + Sized + 'static { type Scalar: Debug + Clone + PartialEq; type ScalarRef<'a>: Debug + Clone + PartialEq; @@ -382,12 +383,9 @@ pub trait AccessType: Debug + Clone + PartialEq + Sized + 'static { fn to_scalar_ref(scalar: &Self::Scalar) -> Self::ScalarRef<'_>; fn try_downcast_scalar<'a>(scalar: &ScalarRef<'a>) -> Option>; - fn try_downcast_column(col: &Column) -> Option; fn try_downcast_domain(domain: &Domain) -> Option; - fn upcast_scalar(scalar: Self::Scalar) -> Scalar; - fn upcast_column(col: Self::Column) -> Column; - fn upcast_domain(domain: Self::Domain) -> Domain; + fn try_downcast_column(col: &Column) -> Option; fn column_len(col: &Self::Column) -> usize; fn index_column(col: &Self::Column, index: usize) -> Option>; @@ -415,12 +413,8 @@ pub trait AccessType: Debug + Clone + PartialEq + Sized + 'static { Self::column_len(col) * std::mem::size_of::() } - /// This is default implementation yet it's not efficient. - #[inline(always)] - fn compare(lhs: Self::ScalarRef<'_>, rhs: Self::ScalarRef<'_>) -> Ordering { - Self::upcast_scalar(Self::to_owned_scalar(lhs)) - .cmp(&Self::upcast_scalar(Self::to_owned_scalar(rhs))) - } + /// Compare two scalar values. + fn compare(lhs: Self::ScalarRef<'_>, rhs: Self::ScalarRef<'_>) -> Ordering; /// Equal comparison between two scalars, some data types not support comparison. #[inline(always)] @@ -459,9 +453,19 @@ pub trait AccessType: Debug + Clone + PartialEq + Sized + 'static { } } +/// ValueType includes the builder method of a data type based on AccessType. pub trait ValueType: AccessType { type ColumnBuilder: Debug + Clone; + /// Convert a scalar value to the generic Scalar type + fn upcast_scalar(scalar: Self::Scalar) -> Scalar; + + /// Convert a domain value to the generic Domain type + fn upcast_domain(domain: Self::Domain) -> Domain; + + /// Convert a column value to the generic Column type + fn upcast_column(col: Self::Column) -> Column; + /// Downcast `ColumnBuilder` to a mutable reference of its inner builder type. /// /// Not every builder can be downcasted successfully. @@ -500,11 +504,7 @@ pub trait ValueType: AccessType { fn build_scalar(builder: Self::ColumnBuilder) -> Self::Scalar; } -pub trait ArgType: ReturnType { - fn data_type() -> DataType; - fn full_domain() -> Self::Domain; -} - +/// Almost all ValueType implement ReturnType, except AnyType. pub trait ReturnType: ValueType { fn create_builder(capacity: usize, generics: &GenericMap) -> Self::ColumnBuilder; @@ -516,11 +516,11 @@ pub trait ReturnType: ValueType { iter: impl Iterator, generics: &GenericMap, ) -> Self::Column { - let mut col = Self::create_builder(iter.size_hint().0, generics); + let mut builder = Self::create_builder(iter.size_hint().0, generics); for item in iter { - Self::push_item(&mut col, Self::to_scalar_ref(&item)); + Self::push_item(&mut builder, Self::to_scalar_ref(&item)); } - Self::build_column(col) + Self::build_column(builder) } fn column_from_ref_iter<'a>( @@ -534,3 +534,9 @@ pub trait ReturnType: ValueType { Self::build_column(col) } } + +/// Almost all ReturnType implement ArgType, except Decimal. +pub trait ArgType: ReturnType { + fn data_type() -> DataType; + fn full_domain() -> Self::Domain; +} diff --git a/src/query/expression/src/types/any.rs b/src/query/expression/src/types/any.rs index 0019ab9b7ba23..3bc86fb3b0373 100755 --- a/src/query/expression/src/types/any.rs +++ b/src/query/expression/src/types/any.rs @@ -55,18 +55,6 @@ impl AccessType for AnyType { Some(domain.clone()) } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - scalar - } - - fn upcast_column(col: Self::Column) -> Column { - col - } - - fn upcast_domain(domain: Self::Domain) -> Domain { - domain - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -105,6 +93,18 @@ impl AccessType for AnyType { impl ValueType for AnyType { type ColumnBuilder = ColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + scalar + } + + fn upcast_domain(domain: Self::Domain) -> Domain { + domain + } + + fn upcast_column(col: Self::Column) -> Column { + col + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { Some(builder) } diff --git a/src/query/expression/src/types/array.rs b/src/query/expression/src/types/array.rs index c6427d20b1233..17338cf4199c4 100755 --- a/src/query/expression/src/types/array.rs +++ b/src/query/expression/src/types/array.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::cmp::Ordering; use std::iter::once; use std::iter::TrustedLen; use std::marker::PhantomData; @@ -55,7 +56,7 @@ impl AccessType for ArrayType { fn try_downcast_scalar<'a>(scalar: &'a ScalarRef) -> Option> { match scalar { - ScalarRef::Array(array) => ::try_downcast_column(array), + ScalarRef::Array(array) => T::try_downcast_column(array), _ => None, } } @@ -66,26 +67,12 @@ impl AccessType for ArrayType { fn try_downcast_domain(domain: &Domain) -> Option { match domain { - Domain::Array(Some(domain)) => { - Some(Some(::try_downcast_domain(domain)?)) - } + Domain::Array(Some(domain)) => Some(Some(T::try_downcast_domain(domain)?)), Domain::Array(None) => Some(None), _ => None, } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Array(::upcast_column(scalar)) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Array(Box::new(col.upcast())) - } - - fn upcast_domain(domain: Self::Domain) -> Domain { - Domain::Array(domain.map(|domain| Box::new(::upcast_domain(domain)))) - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -114,11 +101,38 @@ impl AccessType for ArrayType { fn column_memory_size(col: &Self::Column) -> usize { col.memory_size() } + + fn compare(a: T::Column, b: T::Column) -> Ordering { + let ord = T::column_len(&a).cmp(&T::column_len(&b)); + if ord != Ordering::Equal { + return ord; + } + + for (l, r) in T::iter_column(&a).zip(T::iter_column(&b)) { + let ord = T::compare(l, r); + if ord != Ordering::Equal { + return ord; + } + } + Ordering::Equal + } } impl ValueType for ArrayType { type ColumnBuilder = ArrayColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Array(T::upcast_column(scalar)) + } + + fn upcast_domain(domain: Self::Domain) -> Domain { + Domain::Array(domain.map(|domain| Box::new(T::upcast_domain(domain)))) + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Array(Box::new(col.upcast())) + } + fn try_downcast_builder(_builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { None } @@ -201,7 +215,7 @@ impl ArgType for ArrayType { } } -impl ReturnType for ArrayType { +impl ReturnType for ArrayType { fn create_builder(capacity: usize, generics: &GenericMap) -> Self::ColumnBuilder { ArrayColumnBuilder::with_capacity(capacity, 0, generics) } @@ -258,13 +272,6 @@ impl ArrayColumn { } } - pub fn upcast(self) -> ArrayColumn { - ArrayColumn { - values: T::upcast_column(self.values), - offsets: self.offsets, - } - } - pub fn memory_size(&self) -> usize { T::column_memory_size(&self.underlying_column()) + self.offsets.len() * 8 } @@ -324,6 +331,15 @@ impl ArrayColumn { } } +impl ArrayColumn { + pub fn upcast(self) -> ArrayColumn { + ArrayColumn { + values: T::upcast_column(self.values), + offsets: self.offsets, + } + } +} + impl ArrayColumn { pub fn try_downcast(&self) -> Option> { Some(ArrayColumn { @@ -461,7 +477,7 @@ impl ArrayColumnBuilder { } } -impl ArrayColumnBuilder { +impl ArrayColumnBuilder { pub fn with_capacity(len: usize, values_capacity: usize, generics: &GenericMap) -> Self { let mut offsets = Vec::with_capacity(len + 1); offsets.push(0); diff --git a/src/query/expression/src/types/binary.rs b/src/query/expression/src/types/binary.rs index b94f1a62d401d..2abd0b1910d1c 100644 --- a/src/query/expression/src/types/binary.rs +++ b/src/query/expression/src/types/binary.rs @@ -66,18 +66,6 @@ impl AccessType for BinaryType { } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Binary(scalar) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Binary(col) - } - - fn upcast_domain(_domain: Self::Domain) -> Domain { - Domain::Undefined - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -115,6 +103,18 @@ impl AccessType for BinaryType { impl ValueType for BinaryType { type ColumnBuilder = BinaryColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Binary(scalar) + } + + fn upcast_domain(_domain: Self::Domain) -> Domain { + Domain::Undefined + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Binary(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { match builder { ColumnBuilder::Binary(builder) => Some(builder), diff --git a/src/query/expression/src/types/bitmap.rs b/src/query/expression/src/types/bitmap.rs index 2c1fb6ad025bf..899e9ab8fd6dc 100644 --- a/src/query/expression/src/types/bitmap.rs +++ b/src/query/expression/src/types/bitmap.rs @@ -65,18 +65,6 @@ impl AccessType for BitmapType { } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Bitmap(scalar) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Bitmap(col) - } - - fn upcast_domain(_domain: Self::Domain) -> Domain { - Domain::Undefined - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -115,6 +103,18 @@ impl AccessType for BitmapType { impl ValueType for BitmapType { type ColumnBuilder = BinaryColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Bitmap(scalar) + } + + fn upcast_domain(_domain: Self::Domain) -> Domain { + Domain::Undefined + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Bitmap(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { match builder { ColumnBuilder::Bitmap(builder) => Some(builder), diff --git a/src/query/expression/src/types/boolean.rs b/src/query/expression/src/types/boolean.rs index 3b376405fc9f6..8ba07e31e9b39 100644 --- a/src/query/expression/src/types/boolean.rs +++ b/src/query/expression/src/types/boolean.rs @@ -67,18 +67,6 @@ impl AccessType for BooleanType { domain.as_boolean().cloned() } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Boolean(scalar) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Boolean(col) - } - - fn upcast_domain(domain: Self::Domain) -> Domain { - Domain::Boolean(domain) - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -141,6 +129,18 @@ impl AccessType for BooleanType { impl ValueType for BooleanType { type ColumnBuilder = MutableBitmap; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Boolean(scalar) + } + + fn upcast_domain(domain: Self::Domain) -> Domain { + Domain::Boolean(domain) + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Boolean(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { match builder { ColumnBuilder::Boolean(builder) => Some(builder), diff --git a/src/query/expression/src/types/compute_view.rs b/src/query/expression/src/types/compute_view.rs index 68230a1e83576..b7a73e2104ded 100644 --- a/src/query/expression/src/types/compute_view.rs +++ b/src/query/expression/src/types/compute_view.rs @@ -21,7 +21,6 @@ use databend_common_column::buffer::Buffer; use super::simple_type::SimpleType; use super::AccessType; -use super::Scalar; use crate::Column; use crate::Domain; use crate::ScalarRef; @@ -36,10 +35,22 @@ where fn compute_domain(domain: &F::Domain) -> T::Domain; } +impl Compute for T +where T: SimpleType +{ + fn compute(value: &T::Scalar) -> T::Scalar { + *value + } + + fn compute_domain(domain: &T::Domain) -> T::Domain { + *domain + } +} + #[derive(Debug, Clone, PartialEq, Eq)] -pub struct ComputeView(PhantomData<(F, T, C)>); +pub struct ComputeView(PhantomData<(C, F, T)>); -impl AccessType for ComputeView +impl AccessType for ComputeView where F: SimpleType, T: SimpleType, @@ -64,27 +75,14 @@ where F::downcast_scalar(scalar).map(|v| C::compute(&v)) } - fn upcast_scalar(_: Self::Scalar) -> Scalar { - // Consider moving this method to ValueType - unimplemented!() - } - fn try_downcast_column(col: &Column) -> Option { F::downcast_column(col) } - fn upcast_column(col: Self::Column) -> Column { - F::upcast_column(col) - } - fn try_downcast_domain(domain: &Domain) -> Option { F::downcast_domain(domain).map(|domain| C::compute_domain(&domain)) } - fn upcast_domain(_: Self::Domain) -> Domain { - unimplemented!() - } - fn column_len(col: &Self::Column) -> usize { col.len() } diff --git a/src/query/expression/src/types/date.rs b/src/query/expression/src/types/date.rs index c2876f17a39e3..049f5d6dd8911 100644 --- a/src/query/expression/src/types/date.rs +++ b/src/query/expression/src/types/date.rs @@ -29,8 +29,6 @@ use super::number::SimpleDomain; use super::ArgType; use super::DataType; use super::DecimalSize; -use super::GenericMap; -use super::ReturnType; use super::SimpleType; use super::SimpleValueType; use crate::date_helper::DateConverter; @@ -138,27 +136,6 @@ impl ArgType for DateType { } } -impl ReturnType for DateType { - fn create_builder(capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { - Vec::with_capacity(capacity) - } - - fn column_from_vec(vec: Vec, _generics: &GenericMap) -> Self::Column { - vec.into() - } - - fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { - iter.collect() - } - - fn column_from_ref_iter<'a>( - iter: impl Iterator>, - _: &GenericMap, - ) -> Self::Column { - iter.collect() - } -} - #[inline] pub fn string_to_date( date_str: impl AsRef<[u8]>, diff --git a/src/query/expression/src/types/decimal.rs b/src/query/expression/src/types/decimal.rs index 72fd202af4c0a..59c24bd2cb9ea 100644 --- a/src/query/expression/src/types/decimal.rs +++ b/src/query/expression/src/types/decimal.rs @@ -53,15 +53,12 @@ use super::compute_view::Compute; use super::compute_view::ComputeView; use super::AccessType; use super::AnyType; -use super::ArgType; -use super::DataType; -use super::GenericMap; -use super::ReturnType; use super::SimpleDomain; use super::SimpleType; use super::SimpleValueType; use super::ValueType; use crate::utils::arrow::buffer_into_mut; +use crate::with_decimal_mapped_type; use crate::with_decimal_type; use crate::Column; use crate::ColumnBuilder; @@ -73,6 +70,7 @@ use crate::Value; #[derive(Debug, Clone, PartialEq, Eq)] pub struct CoreDecimal(PhantomData); +pub type Decimal64Type = DecimalType; pub type Decimal128Type = DecimalType; pub type Decimal256Type = DecimalType; @@ -150,40 +148,15 @@ impl SimpleType for CoreDecimal { } } -impl ArgType for DecimalType { - fn data_type() -> DataType { - Num::data_type() - } - - fn full_domain() -> Self::Domain { +impl DecimalType { + pub fn full_domain(size: &DecimalSize) -> SimpleDomain { SimpleDomain { - min: Num::MIN, - max: Num::MAX, + min: Num::min_for_precision(size.precision), + max: Num::max_for_precision(size.precision), } } } -impl ReturnType for DecimalType { - fn create_builder(capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { - Vec::with_capacity(capacity) - } - - fn column_from_vec(vec: Vec, _generics: &GenericMap) -> Self::Column { - vec.into() - } - - fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { - iter.collect() - } - - fn column_from_ref_iter<'a>( - iter: impl Iterator>, - _: &GenericMap, - ) -> Self::Column { - iter.collect() - } -} - #[derive( Clone, Copy, @@ -196,55 +169,70 @@ impl ReturnType for DecimalType { BorshDeserialize, )] pub enum DecimalScalar { + Decimal64(i64, DecimalSize), Decimal128(i128, DecimalSize), Decimal256(i256, DecimalSize), } impl DecimalScalar { pub fn to_float64(&self) -> f64 { - match self { - DecimalScalar::Decimal128(v, size) => i128::to_float64(*v, size.scale()), - DecimalScalar::Decimal256(v, size) => i256::to_float64(*v, size.scale()), - } + with_decimal_type!(|DECIMAL| match self { + DecimalScalar::DECIMAL(v, size) => v.to_float64(size.scale), + }) } + pub fn is_positive(&self) -> bool { - match self { - DecimalScalar::Decimal128(v, _) => i128::is_positive(*v), - DecimalScalar::Decimal256(v, _) => i256::is_positive(*v), - } + with_decimal_type!(|DECIMAL| match self { + DecimalScalar::DECIMAL(v, _) => v.is_positive(), + }) + } + + pub fn size(&self) -> DecimalSize { + with_decimal_type!(|DECIMAL| match self { + DecimalScalar::DECIMAL(_, size) => *size, + }) + } + + pub fn as_decimal(&self) -> D { + with_decimal_type!(|DECIMAL| match self { + DecimalScalar::DECIMAL(value, _) => value.as_decimal(), + }) } } #[derive(Clone, PartialEq, EnumAsInner)] pub enum DecimalColumn { + Decimal64(Buffer, DecimalSize), Decimal128(Buffer, DecimalSize), Decimal256(Buffer, DecimalSize), } #[derive(Clone, PartialEq, EnumAsInner, Debug)] pub enum DecimalColumnVec { + Decimal64(Vec>, DecimalSize), Decimal128(Vec>, DecimalSize), Decimal256(Vec>, DecimalSize), } #[derive(Debug, Clone, PartialEq, Eq, EnumAsInner)] pub enum DecimalColumnBuilder { + Decimal64(Vec, DecimalSize), Decimal128(Vec, DecimalSize), Decimal256(Vec, DecimalSize), } #[derive(Debug, Clone, Copy, PartialEq, Eq, EnumAsInner)] pub enum DecimalDomain { + Decimal64(SimpleDomain, DecimalSize), Decimal128(SimpleDomain, DecimalSize), Decimal256(SimpleDomain, DecimalSize), } impl DecimalDomain { pub fn decimal_size(&self) -> DecimalSize { - match self { - DecimalDomain::Decimal128(_, size) => *size, - DecimalDomain::Decimal256(_, size) => *size, - } + with_decimal_type!(|DECIMAL| match self { + DecimalDomain::DECIMAL(_, size) => *size, + }) } } @@ -310,9 +298,35 @@ impl DecimalSize { self.precision - self.scale } + pub fn can_carried_by_64(&self) -> bool { + self.precision <= MAX_DECIMAL64_PRECISION + } + pub fn can_carried_by_128(&self) -> bool { self.precision <= MAX_DECIMAL128_PRECISION } + + pub fn data_kind(&self) -> DecimalDataKind { + (*self).into() + } + + pub fn best_type(&self) -> DecimalDataType { + if self.can_carried_by_64() { + DecimalDataType::Decimal64(*self) + } else if self.can_carried_by_128() { + DecimalDataType::Decimal128(*self) + } else { + DecimalDataType::Decimal256(*self) + } + } +} + +impl From for DecimalDataType { + fn from(size: DecimalSize) -> Self { + with_decimal_type!(|DECIMAL| match DecimalDataKind::from(size) { + DecimalDataKind::DECIMAL => DecimalDataType::DECIMAL(size), + }) + } } pub trait Decimal: @@ -340,7 +354,7 @@ pub trait Decimal: fn minus_one() -> Self; // 10**scale - fn e(n: u32) -> Self; + fn e(n: u8) -> Self; fn mem_size() -> usize; fn to_u64_array(self) -> Self::U64Array; @@ -362,15 +376,25 @@ pub trait Decimal: fn min_for_precision(precision: u8) -> Self; fn max_for_precision(precision: u8) -> Self; + fn int_part_is_zero(self, scale: u8) -> bool { + if self >= Self::zero() { + self <= Self::max_for_precision(scale) + } else { + self >= Self::min_for_precision(scale) + } + } + fn default_decimal_size() -> DecimalSize; fn from_float(value: f64) -> Self; + + fn from_i64(value: i64) -> Self; fn from_i128>(value: U) -> Self; fn from_i256(value: i256) -> Self; fn from_bigint(value: BigInt) -> Option; fn de_binary(bytes: &mut &[u8]) -> Self; - fn display(self, scale: u8) -> String; + fn to_decimal_string(self, scale: u8) -> String; fn to_float32(self, scale: u8) -> f32; fn to_float64(self, scale: u8) -> f64; @@ -389,9 +413,8 @@ pub trait Decimal: fn upcast_column(col: Buffer, size: DecimalSize) -> Column; fn upcast_domain(domain: SimpleDomain, size: DecimalSize) -> Domain; fn upcast_builder(builder: Vec, size: DecimalSize) -> DecimalColumnBuilder; - fn data_type() -> DataType; - const MIN: Self; - const MAX: Self; + const DECIMAL_MIN: Self; + const DECIMAL_MAX: Self; fn to_column_from_buffer(value: Buffer, size: DecimalSize) -> DecimalColumn; @@ -401,8 +424,10 @@ pub trait Decimal: fn to_scalar(self, size: DecimalSize) -> DecimalScalar; + fn as_decimal(self) -> D; + fn with_size(&self, size: DecimalSize) -> Option { - let multiplier = Self::e(size.scale() as u32); + let multiplier = Self::e(size.scale()); let min_for_precision = Self::min_for_precision(size.precision()); let max_for_precision = Self::max_for_precision(size.precision()); self.checked_mul(multiplier).and_then(|v| { @@ -415,6 +440,265 @@ pub trait Decimal: } } +impl Decimal for i64 { + type U64Array = [u64; 1]; + + fn to_u64_array(self) -> Self::U64Array { + unsafe { std::mem::transmute(self) } + } + + fn from_u64_array(v: Self::U64Array) -> Self { + unsafe { std::mem::transmute(v) } + } + + fn zero() -> Self { + 0 + } + + fn one() -> Self { + 1 + } + + fn minus_one() -> Self { + -1 + } + + fn e(n: u8) -> Self { + const L: usize = MAX_DECIMAL64_PRECISION as usize + 1; + const TAB: [i64; L] = { + const fn gen() -> [i64; L] { + let mut arr = [0; L]; + let mut i = 0; + loop { + if i == L { + break; + } + arr[i] = 10_i64.pow(i as u32); + i += 1; + } + arr + } + gen() + }; + TAB.get(n as usize) + .copied() + .unwrap_or_else(|| 10_i64.pow(n as u32)) + } + + fn mem_size() -> usize { + std::mem::size_of::() + } + + fn signum(self) -> Self { + self.signum() + } + + fn checked_add(self, rhs: Self) -> Option { + self.checked_add(rhs) + } + + fn checked_sub(self, rhs: Self) -> Option { + self.checked_sub(rhs) + } + + fn checked_div(self, rhs: Self) -> Option { + self.checked_div(rhs) + } + + fn checked_mul(self, rhs: Self) -> Option { + self.checked_mul(rhs) + } + + fn checked_rem(self, rhs: Self) -> Option { + self.checked_rem(rhs) + } + + fn do_round_mul(self, rhs: Self, shift_scale: u32, overflow: bool) -> Option { + if shift_scale == 0 { + return Some(self); + } + + if !overflow { + let div = i64::e(shift_scale as u8); + let res = if self.is_negative() == rhs.is_negative() { + (self * rhs + div / 2) / div + } else { + (self * rhs - div / 2) / div + }; + return Some(res); + } + + let div = i128::e(shift_scale as u8); + let res = if self.is_negative() == rhs.is_negative() { + (self as i128 * rhs as i128 + div / 2) / div + } else { + (self as i128 * rhs as i128 - div / 2) / div + }; + + if !(i64::DECIMAL_MIN as i128..=i64::DECIMAL_MAX as i128).contains(&res) { + None + } else { + Some(res as i64) + } + } + + fn do_round_div(self, rhs: Self, mul_scale: u32) -> Option { + let mul = i128::e(mul_scale as u8); + let rhs = rhs as i128; + let res = if self.is_negative() == rhs.is_negative() { + ((self as i128) * mul + rhs / 2) / rhs + } else { + ((self as i128) * mul - rhs / 2) / rhs + }; + Some(res as i64) + } + + fn min_for_precision(precision: u8) -> Self { + -(Self::e(precision) - 1) + } + + fn max_for_precision(precision: u8) -> Self { + Self::e(precision) - 1 + } + + fn default_decimal_size() -> DecimalSize { + DecimalSize { + precision: 18, + scale: 0, + } + } + + fn from_float(value: f64) -> Self { + value as i64 + } + + #[inline] + fn from_i64(value: i64) -> Self { + value + } + + #[inline] + fn from_i128>(value: U) -> Self { + value.into() as i64 + } + + #[inline] + fn from_i256(value: i256) -> Self { + value.as_i64() + } + + fn from_bigint(value: BigInt) -> Option { + value.to_i64() + } + + fn de_binary(bytes: &mut &[u8]) -> Self { + let bs: [u8; std::mem::size_of::()] = + bytes[0..std::mem::size_of::()].try_into().unwrap(); + *bytes = &bytes[std::mem::size_of::()..]; + + i64::from_le_bytes(bs) + } + + fn to_decimal_string(self, scale: u8) -> String { + display_decimal_128(self as i128, scale).to_string() + } + + fn to_float32(self, scale: u8) -> f32 { + let div = 10_f32.powi(scale as i32); + self as f32 / div + } + + fn to_float64(self, scale: u8) -> f64 { + let div = 10_f64.powi(scale as i32); + self as f64 / div + } + + fn to_int(self, scale: u8, rounding_mode: bool) -> Option { + let div = 10i64.checked_pow(scale as u32)?; + let mut val = self / div; + if rounding_mode && scale > 0 { + if let Some(r) = self.checked_rem(div) { + if let Some(m) = r.checked_div(i64::e((scale as u32 - 1) as u8)) { + if m >= 5i64 { + val = val.checked_add(1i64)?; + } else if m <= -5i64 { + val = val.checked_sub(1i64)?; + } + } + } + } + num_traits::cast(val) + } + + fn to_scalar(self, size: DecimalSize) -> DecimalScalar { + DecimalScalar::Decimal64(self, size) + } + + fn try_downcast_column(column: &Column) -> Option<(Buffer, DecimalSize)> { + let column = column.as_decimal()?; + match column { + DecimalColumn::Decimal64(c, size) => Some((c.clone(), *size)), + _ => None, + } + } + + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Vec> { + match builder { + ColumnBuilder::Decimal(DecimalColumnBuilder::Decimal64(s, _)) => Some(s), + _ => None, + } + } + + fn try_downcast_owned_builder(builder: ColumnBuilder) -> Option> { + match builder { + ColumnBuilder::Decimal(DecimalColumnBuilder::Decimal64(s, _)) => Some(s), + _ => None, + } + } + + fn try_downcast_scalar(scalar: &DecimalScalar) -> Option { + match scalar { + DecimalScalar::Decimal64(val, _) => Some(*val), + _ => None, + } + } + + fn try_downcast_domain(domain: &DecimalDomain) -> Option> { + match domain { + DecimalDomain::Decimal64(val, _) => Some(*val), + _ => None, + } + } + + fn upcast_scalar(scalar: Self, size: DecimalSize) -> Scalar { + Scalar::Decimal(DecimalScalar::Decimal64(scalar, size)) + } + + fn upcast_column(col: Buffer, size: DecimalSize) -> Column { + Column::Decimal(DecimalColumn::Decimal64(col, size)) + } + + fn upcast_domain(domain: SimpleDomain, size: DecimalSize) -> Domain { + Domain::Decimal(DecimalDomain::Decimal64(domain, size)) + } + + fn upcast_builder(builder: Vec, size: DecimalSize) -> DecimalColumnBuilder { + DecimalColumnBuilder::Decimal64(builder, size) + } + + const DECIMAL_MIN: i64 = -999999999999999999; + const DECIMAL_MAX: i64 = 999999999999999999; + + fn to_column_from_buffer(value: Buffer, size: DecimalSize) -> DecimalColumn { + DecimalColumn::Decimal64(value, size) + } + + #[inline] + fn as_decimal(self) -> D { + D::from_i64(self) + } +} + impl Decimal for i128 { type U64Array = [u64; 2]; @@ -438,8 +722,26 @@ impl Decimal for i128 { -1_i128 } - fn e(n: u32) -> Self { - 10_i128.pow(n) + fn e(n: u8) -> Self { + const L: usize = MAX_DECIMAL128_PRECISION as usize + 1; + const TAB: [i128; L] = { + const fn gen() -> [i128; L] { + let mut arr = [0; L]; + let mut i = 0; + loop { + if i == L { + break; + } + arr[i] = 10_i128.pow(i as u32); + i += 1; + } + arr + } + gen() + }; + TAB.get(n as usize) + .copied() + .unwrap_or_else(|| 10_i128.pow(n as u32)) } fn mem_size() -> usize { @@ -476,7 +778,7 @@ impl Decimal for i128 { } if !overflow { - let div = i128::e(shift_scale); + let div = i128::e(shift_scale as u8); let res = if self.is_negative() == rhs.is_negative() { (self * rhs + div / 2) / div } else { @@ -486,7 +788,7 @@ impl Decimal for i128 { return Some(res); } - let div = i256::e(shift_scale); + let div = i256::e(shift_scale as u8); let res = if self.is_negative() == rhs.is_negative() { (i256::from(self) * i256::from(rhs) + div / i256::from(2)) / div } else { @@ -501,21 +803,56 @@ impl Decimal for i128 { } fn do_round_div(self, rhs: Self, mul_scale: u32) -> Option { - let mul = i256::e(mul_scale); - if self.is_negative() == rhs.is_negative() { - let res = (i256::from(self) * mul + i256::from(rhs) / i256::from(2)) / i256::from(rhs); - Some(*res.low()) + let mul = i256::e(mul_scale as u8); + let rhs = i256::from(rhs); + let res = if self.is_negative() == rhs.is_negative() { + (i256::from(self) * mul + rhs / i256::from(2)) / rhs } else { - let res = (i256::from(self) * mul - i256::from(rhs) / i256::from(2)) / i256::from(rhs); - Some(*res.low()) - } + (i256::from(self) * mul - rhs / i256::from(2)) / rhs + }; + Some(*res.low()) } fn min_for_precision(to_precision: u8) -> Self { + /// `MIN_DECIMAL_FOR_EACH_PRECISION[p]` holds the minimum `i128` value that can + /// be stored in a [arrow_schema::DataType::Decimal128] value of precision `p` + const MIN_DECIMAL_FOR_EACH_PRECISION: [i128; 38] = { + const fn gen() -> [i128; 38] { + let mut arr = [0; 38]; + let mut i = 0; + loop { + if i == 38 { + break; + } + arr[i] = -(10_i128.pow(1 + i as u32) - 1); + i += 1; + } + arr + } + gen() + }; + MIN_DECIMAL_FOR_EACH_PRECISION[to_precision as usize - 1] } fn max_for_precision(to_precision: u8) -> Self { + /// `MAX_DECIMAL_FOR_EACH_PRECISION[p]` holds the maximum `i128` value that can + /// be stored in [arrow_schema::DataType::Decimal128] value of precision `p` + const MAX_DECIMAL_FOR_EACH_PRECISION: [i128; 38] = { + const fn gen() -> [i128; 38] { + let mut arr = [0; 38]; + let mut i = 0; + loop { + if i == 38 { + break; + } + arr[i] = 10_i128.pow(1 + i as u32) - 1; + i += 1; + } + arr + } + gen() + }; MAX_DECIMAL_FOR_EACH_PRECISION[to_precision as usize - 1] } @@ -530,6 +867,11 @@ impl Decimal for i128 { DecimalColumn::Decimal128(value, size) } + #[inline] + fn as_decimal(self) -> D { + D::from_i128(self) + } + fn from_float(value: f64) -> Self { // still needs to be optimized. // An implementation similar to float64_as_i256 obtained from the ethnum library @@ -561,10 +903,17 @@ impl Decimal for i128 { } } + #[inline] + fn from_i64(value: i64) -> Self { + value as _ + } + + #[inline] fn from_i128>(value: U) -> Self { value.into() } + #[inline] fn from_i256(value: i256) -> Self { value.as_i128() } @@ -581,8 +930,8 @@ impl Decimal for i128 { i128::from_le_bytes(bs) } - fn display(self, scale: u8) -> String { - display_decimal_128(self, scale) + fn to_decimal_string(self, scale: u8) -> String { + display_decimal_128(self, scale).to_string() } fn to_float32(self, scale: u8) -> f32 { @@ -601,7 +950,7 @@ impl Decimal for i128 { if rounding_mode && scale > 0 { // Checking whether numbers need to be added or subtracted to calculate rounding if let Some(r) = self.checked_rem(div) { - if let Some(m) = r.checked_div(i128::e(scale as u32 - 1)) { + if let Some(m) = r.checked_div(i128::e(scale - 1)) { if m >= 5i128 { val = val.checked_add(1i128)?; } else if m <= -5i128 { @@ -670,16 +1019,9 @@ impl Decimal for i128 { DecimalColumnBuilder::Decimal128(builder, size) } - fn data_type() -> DataType { - DataType::Decimal(DecimalSize { - precision: MAX_DECIMAL128_PRECISION, - scale: 0, - }) - } - - const MIN: i128 = -99999999999999999999999999999999999999i128; + const DECIMAL_MIN: i128 = -99999999999999999999999999999999999999i128; - const MAX: i128 = 99999999999999999999999999999999999999i128; + const DECIMAL_MAX: i128 = 99999999999999999999999999999999999999i128; } impl Decimal for i256 { @@ -705,8 +1047,14 @@ impl Decimal for i256 { i256::MINUS_ONE } - fn e(n: u32) -> Self { - (i256::ONE * i256::from(10)).pow(n) + fn e(n: u8) -> Self { + match n { + 0 => i256::ONE, + 1..=MAX_DECIMAL256_PRECISION => { + MAX_DECIMAL256_BYTES_FOR_EACH_PRECISION[n as usize - 1] + i256::ONE + } + _ => i256::from(10).pow(n as u32), + } } fn mem_size() -> usize { @@ -742,7 +1090,7 @@ impl Decimal for i256 { return Some(self); } - let div = i256::e(shift_scale); + let div = i256::e(shift_scale as u8); if !overflow { let ret = if self.is_negative() == rhs.is_negative() { (self * rhs + div / i256::from(2)) / div @@ -788,7 +1136,7 @@ impl Decimal for i256 { return fallback(); } - let mul = i256::e(mul_scale); + let mul = i256::e(mul_scale as u8); let ret: Option = if self.is_negative() == rhs.is_negative() { self.checked_mul(mul) .map(|x| (x + rhs / i256::from(2)) / rhs) @@ -819,10 +1167,17 @@ impl Decimal for i256 { i256(value.as_i256()) } + #[inline] + fn from_i64(value: i64) -> Self { + i256::from(value) + } + + #[inline] fn from_i128>(value: U) -> Self { i256::from(value.into()) } + #[inline] fn from_i256(value: i256) -> Self { value } @@ -846,7 +1201,7 @@ impl Decimal for i256 { let m: u256 = u256::ONE << 255; match ret.cmp(&m) { Ordering::Less => Some(-i256::try_from(ret).unwrap()), - Ordering::Equal => Some(i256::MIN), + Ordering::Equal => Some(i256::DECIMAL_MIN), Ordering::Greater => None, } } @@ -861,8 +1216,8 @@ impl Decimal for i256 { i256::from_le_bytes(bs) } - fn display(self, scale: u8) -> String { - display_decimal_256(self.0, scale) + fn to_decimal_string(self, scale: u8) -> String { + display_decimal_256(self.0, scale).to_string() } fn to_float32(self, scale: u8) -> f32 { @@ -940,26 +1295,25 @@ impl Decimal for i256 { DecimalColumnBuilder::Decimal256(builder, size) } - fn data_type() -> DataType { - DataType::Decimal(DecimalSize { - precision: MAX_DECIMAL256_PRECISION, - scale: 0, - }) - } - - const MIN: i256 = i256(ethnum::int!( + const DECIMAL_MIN: i256 = i256(ethnum::int!( "-9999999999999999999999999999999999999999999999999999999999999999999999999999" )); - const MAX: i256 = i256(ethnum::int!( + const DECIMAL_MAX: i256 = i256(ethnum::int!( "9999999999999999999999999999999999999999999999999999999999999999999999999999" )); fn to_column_from_buffer(value: Buffer, size: DecimalSize) -> DecimalColumn { DecimalColumn::Decimal256(value, size) } + + #[inline] + fn as_decimal(self) -> D { + D::from_i256(self) + } } -pub static MAX_DECIMAL128_PRECISION: u8 = 38; -pub static MAX_DECIMAL256_PRECISION: u8 = 76; +pub const MAX_DECIMAL64_PRECISION: u8 = 18; +pub const MAX_DECIMAL128_PRECISION: u8 = 38; +pub const MAX_DECIMAL256_PRECISION: u8 = 76; #[derive( Debug, @@ -975,20 +1329,12 @@ pub static MAX_DECIMAL256_PRECISION: u8 = 76; EnumAsInner, )] pub enum DecimalDataType { + Decimal64(DecimalSize), Decimal128(DecimalSize), Decimal256(DecimalSize), } impl DecimalDataType { - pub fn from_size(size: DecimalSize) -> Result { - size.validate()?; - if size.can_carried_by_128() { - Ok(DecimalDataType::Decimal128(size)) - } else { - Ok(DecimalDataType::Decimal256(size)) - } - } - pub fn from_value(value: &Value) -> Option<(DecimalDataType, bool)> { match value { Value::Scalar(Scalar::Decimal(scalar)) => with_decimal_type!(|T| match scalar { @@ -1008,6 +1354,12 @@ impl DecimalDataType { } } + pub fn data_kind(&self) -> DecimalDataKind { + with_decimal_type!(|DECIMAL| match self { + DecimalDataType::DECIMAL(_) => DecimalDataKind::DECIMAL, + }) + } + pub fn default_scalar(&self) -> DecimalScalar { with_decimal_type!(|DECIMAL_TYPE| match self { DecimalDataType::DECIMAL_TYPE(size) => DecimalScalar::DECIMAL_TYPE(0.into(), *size), @@ -1040,77 +1392,78 @@ impl DecimalDataType { pub fn max_precision(&self) -> u8 { match self { + DecimalDataType::Decimal64(_) => MAX_DECIMAL64_PRECISION, DecimalDataType::Decimal128(_) => MAX_DECIMAL128_PRECISION, DecimalDataType::Decimal256(_) => MAX_DECIMAL256_PRECISION, } } pub fn max_result_precision(&self, other: &Self) -> u8 { - if matches!(other, DecimalDataType::Decimal128(_)) { - self.max_precision() - } else { - other.max_precision() - } - } - - pub fn belong_diff_precision(precision_a: u8, precision_b: u8) -> bool { - (precision_a > MAX_DECIMAL128_PRECISION && precision_b <= MAX_DECIMAL128_PRECISION) - || (precision_a <= MAX_DECIMAL128_PRECISION && precision_b > MAX_DECIMAL128_PRECISION) + self.max_precision().max(other.max_precision()) } // For div ops, a,b and return must belong to same width types pub fn div_common_type(a: &Self, b: &Self, return_size: DecimalSize) -> Result<(Self, Self)> { - let precision_a = if Self::belong_diff_precision(a.precision(), return_size.precision()) { - return_size.precision() + let return_kind = DecimalDataKind::from(return_size); + + let a = if a.data_kind() == return_kind { + *a } else { - a.precision() + DecimalSize::new(return_size.precision, a.scale())?.into() }; - let precision_b = if Self::belong_diff_precision(b.precision(), return_size.precision()) { - return_size.precision() + let b = if b.data_kind() == return_kind { + *b } else { - b.precision() + DecimalSize::new(return_size.precision, b.scale())?.into() }; - let a_type = Self::from_size(DecimalSize { - precision: precision_a, - scale: a.scale(), - })?; - let b_type = Self::from_size(DecimalSize { - precision: precision_b, - scale: b.scale(), - })?; - - Ok((a_type, b_type)) + Ok((a, b)) } pub fn is_strict(&self) -> bool { + DecimalDataKind::from(self.size()) == self.data_kind() + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DecimalDataKind { + Decimal64, + Decimal128, + Decimal256, +} + +impl From for DecimalDataKind { + fn from(size: DecimalSize) -> Self { + if size.can_carried_by_128() { + DecimalDataKind::Decimal128 + } else { + DecimalDataKind::Decimal256 + } + } +} + +impl DecimalDataKind { + pub fn with_size(&self, size: DecimalSize) -> DecimalDataType { match self { - DecimalDataType::Decimal128(size) if size.can_carried_by_128() => true, - DecimalDataType::Decimal256(size) if !size.can_carried_by_128() => true, - _ => false, + DecimalDataKind::Decimal64 => DecimalDataType::Decimal64(size), + DecimalDataKind::Decimal128 => DecimalDataType::Decimal128(size), + DecimalDataKind::Decimal256 => DecimalDataType::Decimal256(size), } } } impl DecimalScalar { pub fn domain(&self) -> DecimalDomain { - match self { - DecimalScalar::Decimal128(num, size) => DecimalDomain::Decimal128( - SimpleDomain { - min: *num, - max: *num, - }, - *size, - ), - DecimalScalar::Decimal256(num, size) => DecimalDomain::Decimal256( + with_decimal_type!(|DECIMAL| match self { + DecimalScalar::DECIMAL(num, size) => DecimalDomain::DECIMAL( SimpleDomain { min: *num, max: *num, }, *size, ), - } + }) } } @@ -1173,25 +1526,12 @@ impl DecimalColumn { }) } - fn arrow_buffer(&self) -> arrow_buffer::Buffer { - match self { - DecimalColumn::Decimal128(col, _) => col.clone().into(), - DecimalColumn::Decimal256(col, _) => { - let col = unsafe { - std::mem::transmute::<_, Buffer>( - col.clone(), - ) - }; - col.into() - } - } - } - pub fn arrow_data(&self, arrow_type: arrow_schema::DataType) -> ArrayData { #[cfg(debug_assertions)] { match (&arrow_type, self) { - (arrow_schema::DataType::Decimal128(p, s), DecimalColumn::Decimal128(_, size)) + (arrow_schema::DataType::Decimal128(p, s), DecimalColumn::Decimal64(_, size)) + | (arrow_schema::DataType::Decimal128(p, s), DecimalColumn::Decimal128(_, size)) | (arrow_schema::DataType::Decimal256(p, s), DecimalColumn::Decimal256(_, size)) => { assert_eq!(size.precision, *p); assert_eq!(size.scale as i16, *s as i16); @@ -1200,7 +1540,22 @@ impl DecimalColumn { } } - let buffer = self.arrow_buffer(); + let buffer = match self { + DecimalColumn::Decimal64(col, _) => { + let builder = Decimal64As128Type::iter_column(col).collect::>(); + Decimal128Type::build_column(builder).into() + } + DecimalColumn::Decimal128(col, _) => col.clone().into(), + DecimalColumn::Decimal256(col, _) => { + let col = unsafe { + std::mem::transmute::<_, Buffer>( + col.clone(), + ) + }; + col.into() + } + }; + let builder = ArrayDataBuilder::new(arrow_type) .len(self.len()) .buffers(vec![buffer]); @@ -1218,13 +1573,13 @@ impl DecimalColumn { Ok(Self::Decimal128(buffer.into(), decimal_size)) } arrow_schema::DataType::Decimal256(p, s) => { - let buffer: Buffer = buffer.into(); - let buffer = unsafe { std::mem::transmute::<_, Buffer>(buffer) }; - let decimal_size = DecimalSize { precision: *p, scale: *s as u8, }; + + let buffer: Buffer = buffer.into(); + let buffer = unsafe { std::mem::transmute::<_, Buffer>(buffer) }; Ok(Self::Decimal256(buffer, decimal_size)) } data_type => Err(ErrorCode::Unimplemented(format!( @@ -1234,24 +1589,40 @@ impl DecimalColumn { } } + pub fn size(&self) -> DecimalSize { + match self { + DecimalColumn::Decimal64(_, size) + | DecimalColumn::Decimal128(_, size) + | DecimalColumn::Decimal256(_, size) => *size, + } + } + pub fn strict_decimal_data_type(self) -> Self { match &self { - DecimalColumn::Decimal128(buffer, size) => { - if size.can_carried_by_128() { - self - } else { + DecimalColumn::Decimal64(buffer, size) => match size.data_kind() { + DecimalDataKind::Decimal64 | DecimalDataKind::Decimal128 => { + let builder = Decimal64As128Type::iter_column(buffer).collect::>(); + DecimalColumn::Decimal128(Decimal128Type::build_column(builder), *size) + } + DecimalDataKind::Decimal256 => { + let builder = Decimal64As256Type::iter_column(buffer).collect::>(); + DecimalColumn::Decimal256(Decimal256Type::build_column(builder), *size) + } + }, + DecimalColumn::Decimal128(buffer, size) => match size.data_kind() { + DecimalDataKind::Decimal64 | DecimalDataKind::Decimal128 => self, + DecimalDataKind::Decimal256 => { let builder = Decimal128As256Type::iter_column(buffer).collect::>(); DecimalColumn::Decimal256(Decimal256Type::build_column(builder), *size) } - } - DecimalColumn::Decimal256(buffer, size) => { - if size.can_carried_by_128() { + }, + DecimalColumn::Decimal256(buffer, size) => match size.data_kind() { + DecimalDataKind::Decimal64 | DecimalDataKind::Decimal128 => { let builder = Decimal256As128Type::iter_column(buffer).collect::>(); DecimalColumn::Decimal128(Decimal128Type::build_column(builder), *size) - } else { - self } - } + DecimalDataKind::Decimal256 => self, + }, } } @@ -1304,44 +1675,36 @@ impl DecimalColumnBuilder { } pub fn push_repeat(&mut self, item: DecimalScalar, n: usize) { - with_decimal_type!(|DECIMAL_TYPE| match (self, item) { - ( - DecimalColumnBuilder::DECIMAL_TYPE(builder, builder_size), - DecimalScalar::DECIMAL_TYPE(value, value_size), - ) => { - debug_assert_eq!(*builder_size, value_size); + with_decimal_mapped_type!(|DECIMAL| match self { + DecimalColumnBuilder::DECIMAL(builder, builder_size) => { + let value = item.as_decimal::(); + debug_assert_eq!(*builder_size, item.size()); if n == 1 { builder.push(value) } else { builder.resize(builder.len() + n, value) } } - (builder, scalar) => unreachable!("unable to push {scalar:?} to {builder:?}"), }) } pub fn push_default(&mut self) { - with_decimal_type!(|DECIMAL_TYPE| match self { - DecimalColumnBuilder::DECIMAL_TYPE(builder, _) => builder.push(0.into()), + with_decimal_type!(|DECIMAL| match self { + DecimalColumnBuilder::DECIMAL(builder, _) => builder.push(0.into()), }) } - pub fn append_column(&mut self, other: &DecimalColumn) { - with_decimal_type!(|DECIMAL_TYPE| match (self, other) { + pub fn append_column(&mut self, column: &DecimalColumn) { + with_decimal_type!(|DECIMAL_TYPE| match (self, column) { ( DecimalColumnBuilder::DECIMAL_TYPE(builder, builder_size), - DecimalColumn::DECIMAL_TYPE(other, other_size), + DecimalColumn::DECIMAL_TYPE(column, column_size), ) => { - debug_assert_eq!(builder_size, other_size); - builder.extend_from_slice(other); + debug_assert_eq!(builder_size, column_size); + builder.extend_from_slice(column); } - (DecimalColumnBuilder::Decimal128(_, _), DecimalColumn::Decimal256(_, _)) => - unreachable!( - "unable append column(data type: Decimal256) into builder(data type: Decimal128)" - ), - (DecimalColumnBuilder::Decimal256(_, _), DecimalColumn::Decimal128(_, _)) => - unreachable!( - "unable append column(data type: Decimal128) into builder(data type: Decimal256)" + (_b, _c) => unreachable!( + // "unable append column(data type: Decimal256) into builder(data type: Decimal128)" ), }) } @@ -1373,10 +1736,9 @@ impl DecimalColumnBuilder { } pub fn decimal_size(&self) -> DecimalSize { - match self { - DecimalColumnBuilder::Decimal128(_, size) - | DecimalColumnBuilder::Decimal256(_, size) => *size, - } + with_decimal_type!(|DECIMAL| match self { + DecimalColumnBuilder::DECIMAL(_, size) => *size, + }) } } @@ -1420,7 +1782,7 @@ impl PartialOrd for DecimalColumn { macro_rules! with_decimal_type { ( | $t:tt | $($tail:tt)* ) => { match_template::match_template! { - $t = [Decimal128, Decimal256], + $t = [Decimal64, Decimal128, Decimal256], $($tail)* } } @@ -1431,7 +1793,7 @@ macro_rules! with_decimal_mapped_type { (| $t:tt | $($tail:tt)*) => { match_template::match_template! { $t = [ - Decimal128 => i128, Decimal256 => i256 + Decimal64 => i64, Decimal128 => i128, Decimal256 => i256 ], $($tail)* } @@ -1440,7 +1802,7 @@ macro_rules! with_decimal_mapped_type { // MAX decimal256 value of little-endian format for each precision. // Each element is the max value of signed 256-bit integer for the specified precision which // is encoded to the 32-byte width format of little-endian. -pub(crate) const MAX_DECIMAL256_BYTES_FOR_EACH_PRECISION: [i256; 76] = [ +const MAX_DECIMAL256_BYTES_FOR_EACH_PRECISION: [i256; 76] = [ i256::from_le_bytes([ 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1750,7 +2112,7 @@ pub(crate) const MAX_DECIMAL256_BYTES_FOR_EACH_PRECISION: [i256; 76] = [ // MIN decimal256 value of little-endian format for each precision. // Each element is the min value of signed 256-bit integer for the specified precision which // is encoded to the 76-byte width format of little-endian. -pub(crate) const MIN_DECIMAL256_BYTES_FOR_EACH_PRECISION: [i256; 76] = [ +const MIN_DECIMAL256_BYTES_FOR_EACH_PRECISION: [i256; 76] = [ i256::from_le_bytes([ 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -2057,93 +2419,6 @@ pub(crate) const MIN_DECIMAL256_BYTES_FOR_EACH_PRECISION: [i256; 76] = [ ]), ]; -/// Codes from arrow-rs: https://github.com/apache/arrow-rs/blob/9728c676b50b19c06643a23daba4aa4a1dc48055/arrow-data/src/decimal.rs -/// `MAX_DECIMAL_FOR_EACH_PRECISION[p]` holds the maximum `i128` value that can -/// be stored in [arrow_schema::DataType::Decimal128] value of precision `p` -pub const MAX_DECIMAL_FOR_EACH_PRECISION: [i128; 38] = [ - 9, - 99, - 999, - 9999, - 99999, - 999999, - 9999999, - 99999999, - 999999999, - 9999999999, - 99999999999, - 999999999999, - 9999999999999, - 99999999999999, - 999999999999999, - 9999999999999999, - 99999999999999999, - 999999999999999999, - 9999999999999999999, - 99999999999999999999, - 999999999999999999999, - 9999999999999999999999, - 99999999999999999999999, - 999999999999999999999999, - 9999999999999999999999999, - 99999999999999999999999999, - 999999999999999999999999999, - 9999999999999999999999999999, - 99999999999999999999999999999, - 999999999999999999999999999999, - 9999999999999999999999999999999, - 99999999999999999999999999999999, - 999999999999999999999999999999999, - 9999999999999999999999999999999999, - 99999999999999999999999999999999999, - 999999999999999999999999999999999999, - 9999999999999999999999999999999999999, - 99999999999999999999999999999999999999, -]; - -/// `MIN_DECIMAL_FOR_EACH_PRECISION[p]` holds the minimum `i128` value that can -/// be stored in a [arrow_schema::DataType::Decimal128] value of precision `p` -pub const MIN_DECIMAL_FOR_EACH_PRECISION: [i128; 38] = [ - -9, - -99, - -999, - -9999, - -99999, - -999999, - -9999999, - -99999999, - -999999999, - -9999999999, - -99999999999, - -999999999999, - -9999999999999, - -99999999999999, - -999999999999999, - -9999999999999999, - -99999999999999999, - -999999999999999999, - -9999999999999999999, - -99999999999999999999, - -999999999999999999999, - -9999999999999999999999, - -99999999999999999999999, - -999999999999999999999999, - -9999999999999999999999999, - -99999999999999999999999999, - -999999999999999999999999999, - -9999999999999999999999999999, - -99999999999999999999999999999, - -999999999999999999999999999999, - -9999999999999999999999999999999, - -99999999999999999999999999999999, - -999999999999999999999999999999999, - -9999999999999999999999999999999999, - -99999999999999999999999999999999999, - -999999999999999999999999999999999999, - -9999999999999999999999999999999999999, - -99999999999999999999999999999999999999, -]; - /// The wrapper of `ethnum::I256`, used to implement the `BorshSerialize` and `BorshDeserialize` traits. #[derive(Clone, Copy, Default, Eq, Serialize, Deserialize)] #[allow(non_camel_case_types)] @@ -2539,47 +2814,45 @@ impl Ord for i256 { } } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct I128AsI256; +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct DecimalConvert(std::marker::PhantomData<(F, T)>); -impl Compute, CoreDecimal> for I128AsI256 { - fn compute(value: &i128) -> i256 { - i256::from(*value) +impl Compute, CoreDecimal> for DecimalConvert +where + F: Decimal, + T: Decimal, +{ + #[inline] + fn compute(value: &F) -> T { + value.as_decimal::() } - fn compute_domain(domain: &SimpleDomain) -> SimpleDomain { + fn compute_domain(domain: &SimpleDomain) -> SimpleDomain { SimpleDomain { - min: i256::from(domain.min), - max: i256::from(domain.max), + min: domain.min.as_decimal::(), + max: domain.max.as_decimal::(), } } } -pub type Decimal128As256Type = ComputeView, CoreDecimal, I128AsI256>; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct I256ToI128; - -impl Compute, CoreDecimal> for I256ToI128 { - fn compute(value: &i256) -> i128 { - value.as_i128() - } - - fn compute_domain(domain: &SimpleDomain) -> SimpleDomain { - SimpleDomain { - min: domain.min.as_i128(), - max: domain.max.as_i128(), - } - } +macro_rules! decimal_convert_type { + ($from:ty, $to:ty, $alias:ident, $compat:ident) => { + pub type $alias = + ComputeView, CoreDecimal<$from>, CoreDecimal<$to>>; + pub type $compat = DecimalConvert<$from, $to>; + }; } -pub type Decimal256As128Type = ComputeView, CoreDecimal, I256ToI128>; +decimal_convert_type!(i64, i128, Decimal64As128Type, I64ToI128); +decimal_convert_type!(i128, i64, Decimal128As64Type, I128ToI64); +decimal_convert_type!(i64, i256, Decimal64As256Type, I64ToI256); +decimal_convert_type!(i128, i256, Decimal128As256Type, I128ToI256); +decimal_convert_type!(i256, i128, Decimal256As128Type, I256ToI128); +decimal_convert_type!(i256, i64, Decimal256As64Type, I256ToI64); #[cfg(test)] mod tests { use super::*; - use crate::types::Decimal128Type; - use crate::types::Decimal256Type; use crate::types::ValueType; #[test] @@ -2595,7 +2868,7 @@ mod tests { ]; let size = DecimalSize::new_unchecked(38, 10); - let col_128 = Decimal128Type::from_data_with_size(test_values.clone(), size); + let col_128 = Decimal128Type::from_data_with_size(test_values.clone(), Some(size)); let downcast_col = Decimal128As256Type::try_downcast_column(&col_128).unwrap(); let builder: Vec = Decimal128As256Type::iter_column(&downcast_col).collect(); @@ -2619,4 +2892,15 @@ mod tests { assert_eq!(got, want); } } + + #[test] + fn test_min_max_for_precision() { + assert_eq!(i128::max_for_precision(1), 9); + assert_eq!(i128::max_for_precision(2), 99); + assert_eq!(i128::max_for_precision(38), i128::DECIMAL_MAX); + + assert_eq!(i128::min_for_precision(1), -9); + assert_eq!(i128::min_for_precision(2), -99); + assert_eq!(i128::min_for_precision(38), i128::DECIMAL_MIN); + } } diff --git a/src/query/expression/src/types/empty_array.rs b/src/query/expression/src/types/empty_array.rs index 1b8935fccb639..4f35f7dceb605 100644 --- a/src/query/expression/src/types/empty_array.rs +++ b/src/query/expression/src/types/empty_array.rs @@ -12,13 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::ReturnType; use super::ZeroSizeType; use super::ZeroSizeValueType; use crate::property::Domain; use crate::types::ArgType; use crate::types::DataType; -use crate::types::GenericMap; use crate::values::Column; use crate::values::Scalar; use crate::ColumnBuilder; @@ -89,20 +87,3 @@ impl ArgType for EmptyArrayType { fn full_domain() -> Self::Domain {} } - -impl ReturnType for EmptyArrayType { - fn create_builder(_capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { - 0 - } - - fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { - iter.count() - } - - fn column_from_ref_iter<'a>( - iter: impl Iterator>, - _: &GenericMap, - ) -> Self::Column { - iter.count() - } -} diff --git a/src/query/expression/src/types/empty_map.rs b/src/query/expression/src/types/empty_map.rs index 701e02e7f8db6..2a647ed8b0dcb 100644 --- a/src/query/expression/src/types/empty_map.rs +++ b/src/query/expression/src/types/empty_map.rs @@ -12,13 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::ReturnType; use super::ZeroSizeType; use super::ZeroSizeValueType; use crate::property::Domain; use crate::types::ArgType; use crate::types::DataType; -use crate::types::GenericMap; use crate::values::Column; use crate::values::Scalar; use crate::ColumnBuilder; @@ -89,20 +87,3 @@ impl ArgType for EmptyMapType { fn full_domain() -> Self::Domain {} } - -impl ReturnType for EmptyMapType { - fn create_builder(_capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { - 0 - } - - fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { - iter.count() - } - - fn column_from_ref_iter<'a>( - iter: impl Iterator>, - _: &GenericMap, - ) -> Self::Column { - iter.count() - } -} diff --git a/src/query/expression/src/types/generic.rs b/src/query/expression/src/types/generic.rs index 116c00a704ee9..a39cc52c5d98b 100755 --- a/src/query/expression/src/types/generic.rs +++ b/src/query/expression/src/types/generic.rs @@ -59,18 +59,6 @@ impl AccessType for GenericType { Some(domain.clone()) } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - scalar - } - - fn upcast_column(col: Self::Column) -> Column { - col - } - - fn upcast_domain(domain: Self::Domain) -> Domain { - domain - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -109,6 +97,18 @@ impl AccessType for GenericType { impl ValueType for GenericType { type ColumnBuilder = ColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + scalar + } + + fn upcast_domain(domain: Self::Domain) -> Domain { + domain + } + + fn upcast_column(col: Self::Column) -> Column { + col + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { Some(builder) } diff --git a/src/query/expression/src/types/geography.rs b/src/query/expression/src/types/geography.rs index 57be1a157d534..c4e9409e16dab 100644 --- a/src/query/expression/src/types/geography.rs +++ b/src/query/expression/src/types/geography.rs @@ -142,18 +142,6 @@ impl AccessType for GeographyType { } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Geography(scalar) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Geography(col) - } - - fn upcast_domain(_domain: Self::Domain) -> Domain { - Domain::Undefined - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -192,6 +180,18 @@ impl AccessType for GeographyType { impl ValueType for GeographyType { type ColumnBuilder = BinaryColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Geography(scalar) + } + + fn upcast_domain(_domain: Self::Domain) -> Domain { + Domain::Undefined + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Geography(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { match builder { ColumnBuilder::Geography(builder) => Some(builder), diff --git a/src/query/expression/src/types/geometry.rs b/src/query/expression/src/types/geometry.rs index 65a5714e9e477..bb43436c38f57 100644 --- a/src/query/expression/src/types/geometry.rs +++ b/src/query/expression/src/types/geometry.rs @@ -69,18 +69,6 @@ impl AccessType for GeometryType { } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Geometry(scalar) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Geometry(col) - } - - fn upcast_domain(_domain: Self::Domain) -> Domain { - Domain::Undefined - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -119,6 +107,18 @@ impl AccessType for GeometryType { impl ValueType for GeometryType { type ColumnBuilder = BinaryColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Geometry(scalar) + } + + fn upcast_domain(_domain: Self::Domain) -> Domain { + Domain::Undefined + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Geometry(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { match builder { ColumnBuilder::Geometry(builder) => Some(builder), diff --git a/src/query/expression/src/types/interval.rs b/src/query/expression/src/types/interval.rs index cefb23de3994e..b03298272d0fd 100644 --- a/src/query/expression/src/types/interval.rs +++ b/src/query/expression/src/types/interval.rs @@ -20,12 +20,10 @@ use databend_common_column::types::months_days_micros; use databend_common_io::Interval; use super::number::SimpleDomain; -use super::ReturnType; use crate::property::Domain; use crate::types::ArgType; use crate::types::DataType; use crate::types::DecimalSize; -use crate::types::GenericMap; use crate::types::SimpleType; use crate::types::SimpleValueType; use crate::values::Column; @@ -132,27 +130,6 @@ impl ArgType for IntervalType { } } -impl ReturnType for IntervalType { - fn create_builder(capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { - Vec::with_capacity(capacity) - } - - fn column_from_vec(vec: Vec, _generics: &GenericMap) -> Self::Column { - vec.into() - } - - fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { - iter.collect() - } - - fn column_from_ref_iter<'a>( - iter: impl Iterator>, - _: &GenericMap, - ) -> Self::Column { - iter.collect() - } -} - #[inline] pub fn string_to_interval(interval_str: &str) -> databend_common_exception::Result { Interval::from_string(interval_str) diff --git a/src/query/expression/src/types/map.rs b/src/query/expression/src/types/map.rs index e655bcbcd3e29..ed4753b04dfa9 100755 --- a/src/query/expression/src/types/map.rs +++ b/src/query/expression/src/types/map.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::cmp::Ordering; use std::iter::TrustedLen; use std::marker::PhantomData; use std::ops::Range; @@ -80,21 +81,6 @@ impl AccessType for KvPair { } } - fn upcast_scalar((k, v): Self::Scalar) -> Scalar { - Scalar::Tuple(vec![K::upcast_scalar(k), V::upcast_scalar(v)]) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Tuple(vec![ - K::upcast_column(col.keys), - V::upcast_column(col.values), - ]) - } - - fn upcast_domain((k, v): Self::Domain) -> Domain { - Domain::Tuple(vec![K::upcast_domain(k), V::upcast_domain(v)]) - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -122,11 +108,37 @@ impl AccessType for KvPair { fn column_memory_size(col: &Self::Column) -> usize { col.memory_size() } + + #[inline(always)] + fn compare( + (lhs_k, lhs_v): Self::ScalarRef<'_>, + (rhs_k, rhs_v): Self::ScalarRef<'_>, + ) -> Ordering { + match K::compare(lhs_k, rhs_k) { + Ordering::Equal => V::compare(lhs_v, rhs_v), + ord => ord, + } + } } impl ValueType for KvPair { type ColumnBuilder = KvColumnBuilder; + fn upcast_scalar((k, v): Self::Scalar) -> Scalar { + Scalar::Tuple(vec![K::upcast_scalar(k), V::upcast_scalar(v)]) + } + + fn upcast_domain((k, v): Self::Domain) -> Domain { + Domain::Tuple(vec![K::upcast_domain(k), V::upcast_domain(v)]) + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Tuple(vec![ + K::upcast_column(col.keys), + V::upcast_column(col.values), + ]) + } + fn try_downcast_builder(_builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { None } @@ -193,7 +205,7 @@ impl ArgType for KvPair { } } -impl ReturnType for KvPair { +impl ReturnType for KvPair { fn create_builder(capacity: usize, generics: &GenericMap) -> Self::ColumnBuilder { KvColumnBuilder::with_capacity(capacity, generics) } @@ -296,7 +308,7 @@ impl KvColumnBuilder { } } -impl KvColumnBuilder { +impl KvColumnBuilder { pub fn with_capacity(capacity: usize, generics: &GenericMap) -> Self { Self { keys: K::create_builder(capacity, generics), @@ -366,20 +378,6 @@ impl AccessType for MapType { } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Map(KvPair::::upcast_column(scalar)) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Map(Box::new(col.upcast())) - } - - fn upcast_domain(domain: Self::Domain) -> Domain { - Domain::Map( - domain.map(|domain| Box::new( as AccessType>::upcast_domain(domain))), - ) - } - fn column_len(col: &Self::Column) -> usize { MapInternal::::column_len(col) } @@ -408,11 +406,28 @@ impl AccessType for MapType { fn column_memory_size(col: &Self::Column) -> usize { MapInternal::::column_memory_size(col) } + + #[inline(always)] + fn compare(lhs: Self::ScalarRef<'_>, rhs: Self::ScalarRef<'_>) -> std::cmp::Ordering { + MapInternal::::compare(lhs, rhs) + } } impl ValueType for MapType { type ColumnBuilder = as ValueType>::ColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Map(KvPair::::upcast_column(scalar)) + } + + fn upcast_domain(domain: Self::Domain) -> Domain { + Domain::Map(domain.map(|domain| Box::new(KvPair::::upcast_domain(domain)))) + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Map(Box::new(col.upcast())) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { MapInternal::::try_downcast_builder(builder) } @@ -472,7 +487,7 @@ impl ArgType for MapType { } } -impl ReturnType for MapType { +impl ReturnType for MapType { fn create_builder(capacity: usize, generics: &GenericMap) -> Self::ColumnBuilder { MapInternal::::create_builder(capacity, generics) } diff --git a/src/query/expression/src/types/null.rs b/src/query/expression/src/types/null.rs index 6c908c3c057b0..5f3a76fe50d6c 100644 --- a/src/query/expression/src/types/null.rs +++ b/src/query/expression/src/types/null.rs @@ -13,13 +13,11 @@ // limitations under the License. use super::nullable::NullableDomain; -use super::ReturnType; use super::ZeroSizeType; use super::ZeroSizeValueType; use crate::property::Domain; use crate::types::ArgType; use crate::types::DataType; -use crate::types::GenericMap; use crate::values::Column; use crate::values::Scalar; use crate::ColumnBuilder; @@ -96,20 +94,3 @@ impl ArgType for NullType { fn full_domain() -> Self::Domain {} } - -impl ReturnType for NullType { - fn create_builder(_capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { - 0 - } - - fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { - iter.count() - } - - fn column_from_ref_iter<'a>( - iter: impl Iterator>, - _: &GenericMap, - ) -> Self::Column { - iter.count() - } -} diff --git a/src/query/expression/src/types/nullable.rs b/src/query/expression/src/types/nullable.rs index b1e3d401b29d9..59ace5920f2f6 100755 --- a/src/query/expression/src/types/nullable.rs +++ b/src/query/expression/src/types/nullable.rs @@ -85,24 +85,6 @@ impl AccessType for NullableType { } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - match scalar { - Some(scalar) => T::upcast_scalar(scalar), - None => Scalar::Null, - } - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Nullable(Box::new(col.upcast())) - } - - fn upcast_domain(domain: Self::Domain) -> Domain { - Domain::Nullable(NullableDomain { - has_null: domain.has_null, - value: domain.value.map(|value| Box::new(T::upcast_domain(*value))), - }) - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -178,6 +160,27 @@ impl AccessType for NullableType { impl ValueType for NullableType { type ColumnBuilder = NullableColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + match scalar { + Some(scalar) => T::upcast_scalar(scalar), + None => Scalar::Null, + } + } + + fn upcast_domain(domain: Self::Domain) -> Domain { + Domain::Nullable(NullableDomain { + has_null: domain.has_null, + value: domain.value.map(|value| Box::new(T::upcast_domain(*value))), + }) + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Nullable(Box::new(NullableColumn::new( + T::upcast_column(col.column), + col.validity, + ))) + } + fn try_downcast_builder(_builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { None } @@ -275,7 +278,7 @@ impl ArgType for NullableType { } } -impl ReturnType for NullableType { +impl ReturnType for NullableType { fn create_builder(capacity: usize, generics: &GenericMap) -> Self::ColumnBuilder { NullableColumnBuilder::with_capacity(capacity, generics) } @@ -294,15 +297,8 @@ pub struct NullableColumnVec { } impl NullableColumn { - // though column and validity are public - // we should better use new to create a new instance to ensure the validity and column are consistent - // todo: make column and validity private - pub fn new(column: T::Column, validity: Bitmap) -> Self { + pub fn new_access_type(column: T::Column, validity: Bitmap) -> Self { debug_assert_eq!(T::column_len(&column), validity.len()); - debug_assert!(!matches!( - T::upcast_column(column.clone()), - Column::Nullable(_) - )); NullableColumn { column, validity } } @@ -359,21 +355,37 @@ impl NullableColumn { } } - pub fn upcast(self) -> NullableColumn { - NullableColumn::new(T::upcast_column(self.column), self.validity) - } - pub fn memory_size(&self) -> usize { T::column_memory_size(&self.column) + self.validity.as_slice().0.len() } } +impl NullableColumn { + // though column and validity are public + // we should better use new to create a new instance to ensure the validity and column are consistent + // todo: make column and validity private + pub fn new(column: T::Column, validity: Bitmap) -> Self { + debug_assert_eq!(T::column_len(&column), validity.len()); + debug_assert!(!matches!( + T::upcast_column(column.clone()), + Column::Nullable(_) + )); + NullableColumn { column, validity } + } + + pub fn upcast(self) -> NullableColumn { + NullableColumn::new(T::upcast_column(self.column), self.validity) + } +} + impl NullableColumn { pub fn try_downcast(&self) -> Option> { - Some(NullableColumn::new( - T::try_downcast_column(&self.column)?, - self.validity.clone(), - )) + let inner = T::try_downcast_column(&self.column)?; + debug_assert_eq!(T::column_len(&inner), self.validity.len()); + Some(NullableColumn { + column: inner, + validity: self.validity.clone(), + }) } pub fn new_column(column: Column, validity: Bitmap) -> Column { @@ -482,7 +494,7 @@ impl NullableColumnBuilder { } } -impl NullableColumnBuilder { +impl NullableColumnBuilder { pub fn with_capacity(capacity: usize, generics: &GenericMap) -> Self { NullableColumnBuilder { builder: T::create_builder(capacity, generics), diff --git a/src/query/expression/src/types/number.rs b/src/query/expression/src/types/number.rs index 1ea873e2ebecc..83c2399b636ae 100644 --- a/src/query/expression/src/types/number.rs +++ b/src/query/expression/src/types/number.rs @@ -33,11 +33,9 @@ use serde::Deserialize; use serde::Serialize; use super::decimal::DecimalSize; -use super::ReturnType; use crate::property::Domain; use crate::types::ArgType; use crate::types::DataType; -use crate::types::GenericMap; use crate::types::SimpleType; use crate::types::SimpleValueType; use crate::utils::arrow::buffer_into_mut; @@ -192,27 +190,6 @@ impl ArgType for NumberType { } } -impl ReturnType for NumberType { - fn create_builder(capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { - Vec::with_capacity(capacity) - } - - fn column_from_vec(vec: Vec, _generics: &GenericMap) -> Self::Column { - vec.into() - } - - fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { - iter.collect() - } - - fn column_from_ref_iter<'a>( - iter: impl Iterator>, - _: &GenericMap, - ) -> Self::Column { - iter.collect() - } -} - #[derive( Debug, Clone, diff --git a/src/query/expression/src/types/simple_type.rs b/src/query/expression/src/types/simple_type.rs index a3c9458565818..800b25d4d0de8 100644 --- a/src/query/expression/src/types/simple_type.rs +++ b/src/query/expression/src/types/simple_type.rs @@ -21,6 +21,8 @@ use databend_common_column::buffer::Buffer; use super::AccessType; use super::DecimalSize; +use super::GenericMap; +use super::ReturnType; use super::Scalar; use super::ValueType; use crate::arrow::buffer_into_mut; @@ -105,18 +107,6 @@ impl AccessType for SimpleValueType { T::downcast_domain(domain) } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - T::upcast_scalar(scalar) - } - - fn upcast_column(col: Buffer) -> Column { - T::upcast_column(col) - } - - fn upcast_domain(domain: Self::Domain) -> Domain { - T::upcast_domain(domain) - } - fn column_len(buffer: &Buffer) -> usize { buffer.len() } @@ -188,6 +178,18 @@ impl AccessType for SimpleValueType { impl ValueType for SimpleValueType { type ColumnBuilder = Vec; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + T::upcast_scalar(scalar) + } + + fn upcast_domain(domain: Self::Domain) -> Domain { + T::upcast_domain(domain) + } + + fn upcast_column(col: Buffer) -> Column { + T::upcast_column(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Vec> { T::downcast_builder(builder) } @@ -240,3 +242,9 @@ impl ValueType for SimpleValueType { builder[0] } } + +impl ReturnType for SimpleValueType { + fn create_builder(capacity: usize, _: &GenericMap) -> Self::ColumnBuilder { + Vec::with_capacity(capacity) + } +} diff --git a/src/query/expression/src/types/string.rs b/src/query/expression/src/types/string.rs index 2f81527c39c56..a74b77b12a425 100644 --- a/src/query/expression/src/types/string.rs +++ b/src/query/expression/src/types/string.rs @@ -64,18 +64,6 @@ impl AccessType for StringType { domain.as_string().cloned() } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::String(scalar) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::String(col) - } - - fn upcast_domain(domain: Self::Domain) -> Domain { - Domain::String(domain) - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -144,6 +132,18 @@ impl AccessType for StringType { impl ValueType for StringType { type ColumnBuilder = StringColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::String(scalar) + } + + fn upcast_domain(domain: Self::Domain) -> Domain { + Domain::String(domain) + } + + fn upcast_column(col: Self::Column) -> Column { + Column::String(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { match builder { ColumnBuilder::String(builder) => Some(builder), diff --git a/src/query/expression/src/types/timestamp.rs b/src/query/expression/src/types/timestamp.rs index 45a63095c89c3..9faacc7a9542e 100644 --- a/src/query/expression/src/types/timestamp.rs +++ b/src/query/expression/src/types/timestamp.rs @@ -31,8 +31,6 @@ use crate::property::Domain; use crate::types::ArgType; use crate::types::DataType; use crate::types::DecimalSize; -use crate::types::GenericMap; -use crate::types::ReturnType; use crate::types::SimpleType; use crate::types::SimpleValueType; use crate::utils::date_helper::DateConverter; @@ -162,27 +160,6 @@ impl ArgType for TimestampType { } } -impl ReturnType for TimestampType { - fn create_builder(capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { - Vec::with_capacity(capacity) - } - - fn column_from_vec(vec: Vec, _generics: &GenericMap) -> Self::Column { - vec.into() - } - - fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { - iter.collect() - } - - fn column_from_ref_iter<'a>( - iter: impl Iterator>, - _: &GenericMap, - ) -> Self::Column { - iter.collect() - } -} - pub fn microseconds_to_seconds(micros: i64) -> i64 { micros / MICROS_PER_SEC } diff --git a/src/query/expression/src/types/variant.rs b/src/query/expression/src/types/variant.rs index 9888a5beab9cf..e3213fd1e32df 100644 --- a/src/query/expression/src/types/variant.rs +++ b/src/query/expression/src/types/variant.rs @@ -86,18 +86,6 @@ impl AccessType for VariantType { } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Variant(scalar) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Variant(col) - } - - fn upcast_domain(_domain: Self::Domain) -> Domain { - Domain::Undefined - } - fn column_len(col: &Self::Column) -> usize { col.len() } @@ -138,6 +126,18 @@ impl AccessType for VariantType { impl ValueType for VariantType { type ColumnBuilder = BinaryColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Variant(scalar) + } + + fn upcast_domain(_domain: Self::Domain) -> Domain { + Domain::Undefined + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Variant(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { match builder { ColumnBuilder::Variant(builder) => Some(builder), @@ -241,6 +241,14 @@ pub fn cast_scalar_to_variant( NumberScalar::Float64(n) => n.0.into(), }, ScalarRef::Decimal(x) => match x { + DecimalScalar::Decimal64(value, size) => { + let dec = jsonb::Decimal128 { + precision: size.precision(), + scale: size.scale(), + value: value as i128, + }; + jsonb::Value::Number(jsonb::Number::Decimal128(dec)) + } DecimalScalar::Decimal128(value, size) => { let dec = jsonb::Decimal128 { precision: size.precision(), diff --git a/src/query/expression/src/types/vector.rs b/src/query/expression/src/types/vector.rs index 0bedfa2ff34ae..5c5a5bed62cd7 100644 --- a/src/query/expression/src/types/vector.rs +++ b/src/query/expression/src/types/vector.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::cmp::Ordering; use std::iter::TrustedLen; use std::ops::Range; @@ -69,18 +70,6 @@ impl AccessType for VectorType { } } - fn upcast_scalar(scalar: Self::Scalar) -> Scalar { - Scalar::Vector(scalar) - } - - fn upcast_column(col: Self::Column) -> Column { - Column::Vector(col) - } - - fn upcast_domain(_domain: Self::Domain) -> Domain { - Domain::Undefined - } - fn column_len<'a>(col: &Self::Column) -> usize { col.len() } @@ -111,11 +100,27 @@ impl AccessType for VectorType { fn column_memory_size(col: &Self::Column) -> usize { col.memory_size() } + + fn compare(lhs: Self::ScalarRef<'_>, rhs: Self::ScalarRef<'_>) -> Ordering { + lhs.partial_cmp(&rhs).unwrap_or(Ordering::Equal) + } } impl ValueType for VectorType { type ColumnBuilder = VectorColumnBuilder; + fn upcast_scalar(scalar: Self::Scalar) -> Scalar { + Scalar::Vector(scalar) + } + + fn upcast_column(col: Self::Column) -> Column { + Column::Vector(col) + } + + fn upcast_domain(_domain: Self::Domain) -> Domain { + Domain::Undefined + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut Self::ColumnBuilder> { match builder { ColumnBuilder::Vector(builder) => Some(builder), diff --git a/src/query/expression/src/types/zero_size_type.rs b/src/query/expression/src/types/zero_size_type.rs index af0d6127bddff..f69cc8c22289d 100644 --- a/src/query/expression/src/types/zero_size_type.rs +++ b/src/query/expression/src/types/zero_size_type.rs @@ -19,6 +19,8 @@ use std::ops::Range; use super::AccessType; use super::DecimalSize; +use super::GenericMap; +use super::ReturnType; use super::Scalar; use super::ValueType; use crate::Column; @@ -57,23 +59,14 @@ impl AccessType for ZeroSizeValueType { fn try_downcast_scalar<'a>(scalar: &ScalarRef<'a>) -> Option> { T::downcast_scalar(scalar) } - fn upcast_scalar(_: ()) -> Scalar { - T::upcast_scalar() - } fn try_downcast_column(col: &Column) -> Option { T::downcast_column(col) } - fn upcast_column(col: Self::Column) -> Column { - T::upcast_column(col) - } fn try_downcast_domain(domain: &Domain) -> Option<()> { T::downcast_domain(domain) } - fn upcast_domain(_: ()) -> Domain { - T::upcast_domain() - } fn column_len(len: &usize) -> usize { *len @@ -140,6 +133,18 @@ impl AccessType for ZeroSizeValueType { impl ValueType for ZeroSizeValueType { type ColumnBuilder = usize; + fn upcast_scalar(_: ()) -> Scalar { + T::upcast_scalar() + } + + fn upcast_domain(_: ()) -> Domain { + T::upcast_domain() + } + + fn upcast_column(col: Self::Column) -> Column { + T::upcast_column(col) + } + fn try_downcast_builder(builder: &mut ColumnBuilder) -> Option<&mut usize> { T::downcast_builder(builder) } @@ -184,3 +189,20 @@ impl ValueType for ZeroSizeValueType { assert_eq!(builder, 1); } } + +impl ReturnType for ZeroSizeValueType { + fn create_builder(_capacity: usize, _generics: &GenericMap) -> Self::ColumnBuilder { + 0 + } + + fn column_from_iter(iter: impl Iterator, _: &GenericMap) -> Self::Column { + iter.count() + } + + fn column_from_ref_iter<'a>( + iter: impl Iterator>, + _: &GenericMap, + ) -> Self::Column { + iter.count() + } +} diff --git a/src/query/expression/src/utils/column_from.rs b/src/query/expression/src/utils/column_from.rs index 18b5216c019fa..f157d220affc4 100755 --- a/src/query/expression/src/utils/column_from.rs +++ b/src/query/expression/src/utils/column_from.rs @@ -39,7 +39,7 @@ macro_rules! impl_from_data { ($T: ident) => { impl FromData<<$T as AccessType>::Scalar> for $T { fn from_data(d: Vec<<$T as AccessType>::Scalar>) -> Column { - <$T as AccessType>::upcast_column($T::column_from_iter(d.into_iter(), &[])) + <$T as ValueType>::upcast_column($T::column_from_iter(d.into_iter(), &[])) } fn from_opt_data(d: Vec::Scalar>>) -> Column { @@ -60,8 +60,6 @@ impl_from_data! { UInt32Type } impl_from_data! { UInt64Type } impl_from_data! { Float32Type } impl_from_data! { Float64Type } -impl_from_data! { Decimal128Type } -impl_from_data! { Decimal256Type } impl_from_data! { BooleanType } impl_from_data! { BinaryType } impl_from_data! { StringType } @@ -118,14 +116,17 @@ impl FromData for Float64Type { } impl DecimalType { - pub fn from_data_with_size>(d: D, size: DecimalSize) -> Column { + pub fn from_data_with_size>(d: D, size: Option) -> Column { Num::upcast_column( Self::column_from_iter(d.as_ref().iter().copied(), &[]), - size, + size.unwrap_or(Num::default_decimal_size()), ) } - pub fn from_opt_data_with_size]>>(d: D, size: DecimalSize) -> Column { + pub fn from_opt_data_with_size]>>( + d: D, + size: Option, + ) -> Column { let mut validity = MutableBitmap::with_capacity(d.as_ref().len()); let mut data = Vec::with_capacity(d.as_ref().len()); for v in d.as_ref() { diff --git a/src/query/expression/src/utils/display.rs b/src/query/expression/src/utils/display.rs index fa66000de7aa5..0ed30f4e8f914 100755 --- a/src/query/expression/src/utils/display.rs +++ b/src/query/expression/src/utils/display.rs @@ -360,6 +360,15 @@ impl Display for NumberScalar { impl Debug for DecimalScalar { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { match self { + DecimalScalar::Decimal64(val, size) => { + write!( + f, + "{}_d64({},{})", + display_decimal_128(*val as i128, size.scale()), + size.precision(), + size.scale() + ) + } DecimalScalar::Decimal128(val, size) => { write!( f, @@ -385,6 +394,9 @@ impl Debug for DecimalScalar { impl Display for DecimalScalar { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { match self { + DecimalScalar::Decimal64(val, size) => { + write!(f, "{}", display_decimal_128(*val as i128, size.scale())) + } DecimalScalar::Decimal128(val, size) => { write!(f, "{}", display_decimal_128(*val, size.scale())) } @@ -427,23 +439,32 @@ impl Debug for NumberColumn { impl Debug for DecimalColumn { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { match self { + DecimalColumn::Decimal64(val, size) => f + .debug_tuple("Decimal64") + .field_with(|f| { + f.debug_list() + .entries( + val.iter() + .map(|x| display_decimal_128(*x as i128, size.scale())), + ) + .finish() + }) + .finish(), DecimalColumn::Decimal128(val, size) => f .debug_tuple("Decimal128") - .field(&format_args!( - "[{}]", - &val.iter() - .map(|x| display_decimal_128(*x, size.scale())) - .join(", ") - )) + .field_with(|f| { + f.debug_list() + .entries(val.iter().map(|x| display_decimal_128(*x, size.scale()))) + .finish() + }) .finish(), DecimalColumn::Decimal256(val, size) => f .debug_tuple("Decimal256") - .field(&format_args!( - "[{}]", - &val.iter() - .map(|x| display_decimal_256(x.0, size.scale())) - .join(", ") - )) + .field_with(|f| { + f.debug_list() + .entries(val.iter().map(|x| display_decimal_256(x.0, size.scale()))) + .finish() + }) .finish(), } } @@ -1135,6 +1156,12 @@ impl Display for NumberDomain { impl Display for DecimalDomain { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { match self { + DecimalDomain::Decimal64(SimpleDomain { min, max }, size) => { + write!(f, "{}", SimpleDomain { + min: display_decimal_128(*min as i128, size.scale()), + max: display_decimal_128(*max as i128, size.scale()), + }) + } DecimalDomain::Decimal128(SimpleDomain { min, max }, size) => { write!(f, "{}", SimpleDomain { min: display_decimal_128(*min, size.scale()), diff --git a/src/query/expression/src/utils/mod.rs b/src/query/expression/src/utils/mod.rs index 3df333953b138..eae1d0df91697 100644 --- a/src/query/expression/src/utils/mod.rs +++ b/src/query/expression/src/utils/mod.rs @@ -35,7 +35,7 @@ use crate::types::decimal::MAX_DECIMAL256_PRECISION; use crate::types::i256; use crate::types::AnyType; use crate::types::DataType; -use crate::types::DecimalDataType; +use crate::types::DecimalDataKind; use crate::types::DecimalSize; use crate::types::NumberScalar; use crate::BlockEntry; @@ -190,15 +190,11 @@ fn shrink_d256(decimal: i256, size: DecimalSize) -> Scalar { } precision = precision.clamp(1, MAX_DECIMAL256_PRECISION); - let size = DecimalSize::new_unchecked(precision, size.scale()); - let decimal_ty = DecimalDataType::from_size(size).unwrap(); - - match decimal_ty { - DecimalDataType::Decimal128(size) => { + let size = DecimalSize::new(precision, size.scale()).unwrap(); + match size.data_kind() { + DecimalDataKind::Decimal64 | DecimalDataKind::Decimal128 => { Scalar::Decimal(DecimalScalar::Decimal128(decimal.as_i128(), size)) } - DecimalDataType::Decimal256(size) => { - Scalar::Decimal(DecimalScalar::Decimal256(decimal, size)) - } + DecimalDataKind::Decimal256 => Scalar::Decimal(DecimalScalar::Decimal256(decimal, size)), } } diff --git a/src/query/expression/src/utils/serialize.rs b/src/query/expression/src/utils/serialize.rs index 24fc3483e8ffb..cb53000ac0a33 100644 --- a/src/query/expression/src/utils/serialize.rs +++ b/src/query/expression/src/utils/serialize.rs @@ -47,7 +47,7 @@ pub fn read_decimal_with_size( let n = match scale_diff.cmp(&0) { Ordering::Less => { - let scale_diff = -scale_diff as u32; + let scale_diff = -scale_diff as u8; let mut round_val = None; if rounding_mode { // Checking whether numbers need to be added or subtracted to calculate rounding @@ -72,7 +72,7 @@ pub fn read_decimal_with_size( } } Ordering::Greater => n - .checked_mul(T::e(scale_diff as u32)) + .checked_mul(T::e(scale_diff as _)) .ok_or_else(decimal_overflow_error)?, Ordering::Equal => n, }; @@ -262,7 +262,7 @@ pub fn read_decimal( n = n .checked_add(T::from_i128((v - b'0') as u64)) .ok_or_else(decimal_overflow_error)?; - digits += zeros + 1; + digits += (zeros as u32) + 1; zeros = 0; } } diff --git a/src/query/expression/src/values.rs b/src/query/expression/src/values.rs index 637c699d54fa8..45d4695b5bdb3 100755 --- a/src/query/expression/src/values.rs +++ b/src/query/expression/src/values.rs @@ -636,6 +636,7 @@ impl ScalarRef<'_> { ScalarRef::Number(NumberScalar::Int16(_)) => 2, ScalarRef::Number(NumberScalar::Int32(_)) => 4, ScalarRef::Number(NumberScalar::Int64(_)) => 8, + ScalarRef::Decimal(DecimalScalar::Decimal64(_, _)) => 8, ScalarRef::Decimal(DecimalScalar::Decimal128(_, _)) => 16, ScalarRef::Decimal(DecimalScalar::Decimal256(_, _)) => 32, ScalarRef::Boolean(_) => 1, @@ -1639,6 +1640,7 @@ impl Column { Column::Number(NumberColumn::Int16(col)) => col.len() * 2, Column::Number(NumberColumn::Int32(col)) => col.len() * 4, Column::Number(NumberColumn::Int64(col)) => col.len() * 8, + Column::Decimal(DecimalColumn::Decimal64(col, _)) => col.len() * 8, Column::Decimal(DecimalColumn::Decimal128(col, _)) => col.len() * 16, Column::Decimal(DecimalColumn::Decimal256(col, _)) => col.len() * 32, Column::Boolean(c) => c.as_slice().0.len(), @@ -1672,6 +1674,7 @@ impl Column { Column::Number(NumberColumn::Int16(col)) => col.len() * 2, Column::Number(NumberColumn::Int32(col)) | Column::Date(col) => col.len() * 4, Column::Number(NumberColumn::Int64(col)) | Column::Timestamp(col) => col.len() * 8, + Column::Decimal(DecimalColumn::Decimal64(col, _)) => col.len() * 8, Column::Decimal(DecimalColumn::Decimal128(col, _)) => col.len() * 16, Column::Decimal(DecimalColumn::Decimal256(col, _)) => col.len() * 32, Column::Interval(col) => col.len() * 16, @@ -1902,6 +1905,9 @@ impl ColumnBuilder { ColumnBuilder::Number(NumberColumnBuilder::Int16(builder)) => builder.len() * 2, ColumnBuilder::Number(NumberColumnBuilder::Int32(builder)) => builder.len() * 4, ColumnBuilder::Number(NumberColumnBuilder::Int64(builder)) => builder.len() * 8, + ColumnBuilder::Decimal(DecimalColumnBuilder::Decimal64(builder, _)) => { + builder.len() * 8 + } ColumnBuilder::Decimal(DecimalColumnBuilder::Decimal128(builder, _)) => { builder.len() * 16 } diff --git a/src/query/expression/tests/it/decimal.rs b/src/query/expression/tests/it/decimal.rs index 181daca0e215e..3121430b2891f 100644 --- a/src/query/expression/tests/it/decimal.rs +++ b/src/query/expression/tests/it/decimal.rs @@ -188,8 +188,8 @@ fn test_from_bigint() { "1".repeat(26), i256::from_str_radix(&"1".repeat(26), 10).unwrap(), ), - (i256::MIN.to_string(), i256::MIN), - (i256::MAX.to_string(), i256::MAX), + (i256::DECIMAL_MIN.to_string(), i256::DECIMAL_MIN), + (i256::DECIMAL_MAX.to_string(), i256::DECIMAL_MAX), ]; for (a, b) in cases { diff --git a/src/query/expression/tests/it/group_by.rs b/src/query/expression/tests/it/group_by.rs index 6b7e6f362554f..295c34d2d35ad 100644 --- a/src/query/expression/tests/it/group_by.rs +++ b/src/query/expression/tests/it/group_by.rs @@ -74,10 +74,10 @@ fn test_group_by_hash_decimal() -> Result<()> { ]; let block = new_block(&vec![ - Decimal128Type::from_data_with_size(decimal_128_values, size_128), - Decimal256Type::from_data_with_size(decimal_256_values, size_128), - Decimal128Type::from_data_with_size(decimal_128_values, size_256), - Decimal256Type::from_data_with_size(decimal_256_values, size_256), + Decimal128Type::from_data_with_size(decimal_128_values, Some(size_128)), + Decimal256Type::from_data_with_size(decimal_256_values, Some(size_128)), + Decimal128Type::from_data_with_size(decimal_128_values, Some(size_256)), + Decimal256Type::from_data_with_size(decimal_256_values, Some(size_256)), ]); let method = DataBlock::choose_hash_method(&block, &[0])?; diff --git a/src/query/expression/tests/it/row.rs b/src/query/expression/tests/it/row.rs index 8f62d6536b119..3d5563f040240 100644 --- a/src/query/expression/tests/it/row.rs +++ b/src/query/expression/tests/it/row.rs @@ -67,13 +67,11 @@ fn test_fixed_width() { let rows = converter.convert_columns(&cols, cols[0].len()); - unsafe { - assert!(rows.index_unchecked(3) < rows.index_unchecked(6)); - assert!(rows.index_unchecked(0) < rows.index_unchecked(1)); - assert!(rows.index_unchecked(3) < rows.index_unchecked(0)); - assert!(rows.index_unchecked(4) < rows.index_unchecked(1)); - assert!(rows.index_unchecked(5) < rows.index_unchecked(4)); - } + assert!(rows.index(3).unwrap() < rows.index(6).unwrap()); + assert!(rows.index(0).unwrap() < rows.index(1).unwrap()); + assert!(rows.index(3).unwrap() < rows.index(0).unwrap()); + assert!(rows.index(4).unwrap() < rows.index(1).unwrap()); + assert!(rows.index(5).unwrap() < rows.index(4).unwrap()); } #[test] @@ -92,16 +90,14 @@ fn test_decimal128() { Some(5456_i128), Some(i128::MAX), ], - DecimalSize::new_unchecked(38, 7), + Some(DecimalSize::new_unchecked(38, 7)), ); let num_rows = col.len(); let rows = converter.convert_columns(&[col], num_rows); - unsafe { - for i in 0..rows.len() - 1 { - assert!(rows.index_unchecked(i) < rows.index_unchecked(i + 1)); - } + for i in 0..rows.len() - 1 { + assert!(rows.index(i).unwrap() < rows.index(i + 1).unwrap()); } } @@ -115,23 +111,70 @@ fn test_decimal256() { let col = Decimal256Type::from_opt_data_with_size( vec![ None, - Some(i256::MIN), + Some(i256::DECIMAL_MIN), Some(i256::from_words(-1, 0)), Some(i256::from_words(-1, i128::MAX)), Some(i256::from_words(0, i128::MAX)), Some(i256::from_words(46_i128, 0)), Some(i256::from_words(46_i128, 5)), - Some(i256::MAX), + Some(i256::DECIMAL_MAX), ], - DecimalSize::new_unchecked(76, 7), + Some(DecimalSize::new_unchecked(76, 7)), ); let num_rows = col.len(); let rows = converter.convert_columns(&[col], num_rows); - unsafe { - for i in 0..rows.len() - 1 { - assert!(rows.index_unchecked(i) < rows.index_unchecked(i + 1)); + for i in 0..rows.len() - 1 { + assert!(rows.index(i).unwrap() < rows.index(i + 1).unwrap()); + } +} + +#[test] +fn test_decimal_view() { + fn run(size: DecimalSize, col: Column) { + let converter = RowConverter::new(vec![SortField::new(DataType::Decimal(size))]).unwrap(); + let num_rows = col.len(); + let rows = converter.convert_columns(&[col], num_rows); + for i in 0..num_rows - 1 { + assert!(rows.index(i).unwrap() <= rows.index(i + 1).unwrap()); + } + } + + { + let data = vec![-100i64, 50i64, 100i64, 200i64, 300i64]; + + for p in [15, 20, 40] { + let size = DecimalSize::new_unchecked(p, 2); + let col = Decimal64Type::from_data_with_size(&data, Some(size)); + run(size, col); + } + } + + { + let data = vec![-1000i128, 500i128, 1500i128, 2000i128, 3000i128]; + + for p in [15, 20, 40] { + let size = DecimalSize::new_unchecked(p, 3); + let col = Decimal128Type::from_data_with_size(&data, Some(size)); + + run(size, col); + } + } + + { + let data = vec![ + i256::from(-5000), + i256::from(10000), + i256::from(15000), + i256::from(20000), + ]; + + for p in [15, 20, 40] { + let size = DecimalSize::new_unchecked(p, 4); + let col = Decimal256Type::from_data_with_size(&data, Some(size)); + + run(size, col); } } } @@ -146,11 +189,9 @@ fn test_bool() { let rows = converter.convert_columns(&[col.clone()], num_rows); - unsafe { - assert!(rows.index_unchecked(2) > rows.index_unchecked(1)); - assert!(rows.index_unchecked(2) > rows.index_unchecked(0)); - assert!(rows.index_unchecked(1) > rows.index_unchecked(0)); - } + assert!(rows.index(2).unwrap() > rows.index(1).unwrap()); + assert!(rows.index(2).unwrap() > rows.index(0).unwrap()); + assert!(rows.index(1).unwrap() > rows.index(0).unwrap()); let converter = RowConverter::new(vec![SortField::new_with_options( DataType::Boolean.wrap_nullable(), @@ -161,11 +202,9 @@ fn test_bool() { let rows = converter.convert_columns(&[col], num_rows); - unsafe { - assert!(rows.index_unchecked(2) < rows.index_unchecked(1)); - assert!(rows.index_unchecked(2) < rows.index_unchecked(0)); - assert!(rows.index_unchecked(1) < rows.index_unchecked(0)); - } + assert!(rows.index(2).unwrap() < rows.index(1).unwrap()); + assert!(rows.index(2).unwrap() < rows.index(0).unwrap()); + assert!(rows.index(1).unwrap() < rows.index(0).unwrap()); } #[test] @@ -193,12 +232,10 @@ fn test_binary() { let num_rows = col.len(); let rows = converter.convert_columns(&[col], num_rows); - unsafe { - assert!(rows.index_unchecked(1) < rows.index_unchecked(0)); - assert!(rows.index_unchecked(2) < rows.index_unchecked(4)); - assert!(rows.index_unchecked(3) < rows.index_unchecked(0)); - assert!(rows.index_unchecked(3) < rows.index_unchecked(1)); - } + assert!(rows.index(1).unwrap() < rows.index(0).unwrap()); + assert!(rows.index(2).unwrap() < rows.index(4).unwrap()); + assert!(rows.index(3).unwrap() < rows.index(0).unwrap()); + assert!(rows.index(3).unwrap() < rows.index(1).unwrap()); const BLOCK_SIZE: usize = 32; @@ -221,18 +258,16 @@ fn test_binary() { RowConverter::new(vec![SortField::new(DataType::Binary.wrap_nullable())]).unwrap(); let rows = converter.convert_columns(&[col.clone()], num_rows); - unsafe { - for i in 0..rows.len() { - for j in i + 1..rows.len() { - assert!( - rows.index_unchecked(i) < rows.index_unchecked(j), - "{} < {} - {:?} < {:?}", - i, - j, - rows.index_unchecked(i), - rows.index_unchecked(j) - ); - } + for i in 0..rows.len() { + for j in i + 1..rows.len() { + assert!( + rows.index(i).unwrap() < rows.index(j).unwrap(), + "{} < {} - {:?} < {:?}", + i, + j, + rows.index(i).unwrap(), + rows.index(j).unwrap() + ); } } @@ -244,18 +279,16 @@ fn test_binary() { .unwrap(); let rows = converter.convert_columns(&[col], num_rows); - unsafe { - for i in 0..rows.len() { - for j in i + 1..rows.len() { - assert!( - rows.index_unchecked(i) > rows.index_unchecked(j), - "{} > {} - {:?} > {:?}", - i, - j, - rows.index_unchecked(i), - rows.index_unchecked(j) - ); - } + for i in 0..rows.len() { + for j in i + 1..rows.len() { + assert!( + rows.index(i).unwrap() > rows.index(j).unwrap(), + "{} > {} - {:?} > {:?}", + i, + j, + rows.index(i).unwrap(), + rows.index(j).unwrap() + ); } } } @@ -270,12 +303,10 @@ fn test_string() { let num_rows = col.len(); let rows = converter.convert_columns(&[col], num_rows); - unsafe { - assert!(rows.index_unchecked(1) < rows.index_unchecked(0)); - assert!(rows.index_unchecked(2) < rows.index_unchecked(4)); - assert!(rows.index_unchecked(3) < rows.index_unchecked(0)); - assert!(rows.index_unchecked(3) < rows.index_unchecked(1)); - } + assert!(rows.index(1).unwrap() < rows.index(0).unwrap()); + assert!(rows.index(2).unwrap() < rows.index(4).unwrap()); + assert!(rows.index(3).unwrap() < rows.index(0).unwrap()); + assert!(rows.index(3).unwrap() < rows.index(1).unwrap()); const BLOCK_SIZE: usize = 32; @@ -295,18 +326,16 @@ fn test_string() { RowConverter::new(vec![SortField::new(DataType::String.wrap_nullable())]).unwrap(); let rows = converter.convert_columns(&[col.clone()], num_rows); - unsafe { - for i in 0..rows.len() { - for j in i + 1..rows.len() { - assert!( - rows.index_unchecked(i) < rows.index_unchecked(j), - "{} < {} - {:?} < {:?}", - i, - j, - rows.index_unchecked(i), - rows.index_unchecked(j) - ); - } + for i in 0..rows.len() { + for j in i + 1..rows.len() { + assert!( + rows.index(i).unwrap() < rows.index(j).unwrap(), + "{} < {} - {:?} < {:?}", + i, + j, + rows.index(i).unwrap(), + rows.index(j).unwrap() + ); } } @@ -318,18 +347,16 @@ fn test_string() { .unwrap(); let rows = converter.convert_columns(&[col], num_rows); - unsafe { - for i in 0..rows.len() { - for j in i + 1..rows.len() { - assert!( - rows.index_unchecked(i) > rows.index_unchecked(j), - "{} > {} - {:?} > {:?}", - i, - j, - rows.index_unchecked(i), - rows.index_unchecked(j) - ); - } + for i in 0..rows.len() { + for j in i + 1..rows.len() { + assert!( + rows.index(i).unwrap() > rows.index(j).unwrap(), + "{} > {} - {:?} > {:?}", + i, + j, + rows.index(i).unwrap(), + rows.index(j).unwrap() + ); } } } @@ -376,18 +403,16 @@ fn test_variant() { let num_rows = col.len(); let rows = converter.convert_columns(&[col.clone()], num_rows); - unsafe { - for i in 0..rows.len() { - for j in i + 1..rows.len() { - assert!( - rows.index_unchecked(i) < rows.index_unchecked(j), - "{} < {} - {:?} < {:?}", - i, - j, - rows.index_unchecked(i), - rows.index_unchecked(j) - ); - } + for i in 0..rows.len() { + for j in i + 1..rows.len() { + assert!( + rows.index(i).unwrap() < rows.index(j).unwrap(), + "{} < {} - {:?} < {:?}", + i, + j, + rows.index(i).unwrap(), + rows.index(j).unwrap() + ); } } @@ -399,18 +424,16 @@ fn test_variant() { .unwrap(); let rows = converter.convert_columns(&[col], num_rows); - unsafe { - for i in 0..rows.len() { - for j in i + 1..rows.len() { - assert!( - rows.index_unchecked(i) > rows.index_unchecked(j), - "{} > {} - {:?} > {:?}", - i, - j, - rows.index_unchecked(i), - rows.index_unchecked(j) - ); - } + for i in 0..rows.len() { + for j in i + 1..rows.len() { + assert!( + rows.index(i).unwrap() > rows.index(j).unwrap(), + "{} > {} - {:?} > {:?}", + i, + j, + rows.index(i).unwrap(), + rows.index(j).unwrap() + ); } } } @@ -461,13 +484,11 @@ fn generate_column(len: usize) -> Column { } fn print_row(cols: &[Column], row: usize) -> String { - unsafe { - let t: Vec<_> = cols - .iter() - .map(|x| format!("{:?}", x.index_unchecked(row))) - .collect(); - t.join(",") - } + let t: Vec<_> = cols + .iter() + .map(|x| format!("{:?}", x.index(row).unwrap())) + .collect(); + t.join(",") } fn print_options(cols: &[(bool, bool)]) -> String { @@ -532,24 +553,22 @@ fn fuzz_test() { let converter = RowConverter::new(fields).unwrap(); let rows = converter.convert_columns(&columns, num_rows); - unsafe { - for i in 0..num_rows { - for j in 0..num_rows { - let row_i = rows.index_unchecked(i); - let row_j = rows.index_unchecked(j); - let row_cmp = row_i.cmp(row_j); - let lex_cmp = comparator.compare(i, j); - assert_eq!( - row_cmp, - lex_cmp, - "\ndata: ({:?} vs {:?})\nrow format: ({:?} vs {:?})\noptions: {:?}", - print_row(&columns, i), - print_row(&columns, j), - row_i, - row_j, - print_options(&options) - ); - } + for i in 0..num_rows { + for j in 0..num_rows { + let row_i = rows.index(i).unwrap(); + let row_j = rows.index(j).unwrap(); + let row_cmp = row_i.cmp(row_j); + let lex_cmp = comparator.compare(i, j); + assert_eq!( + row_cmp, + lex_cmp, + "\ndata: ({:?} vs {:?})\nrow format: ({:?} vs {:?})\noptions: {:?}", + print_row(&columns, i), + print_row(&columns, j), + row_i, + row_j, + print_options(&options) + ); } } } diff --git a/src/query/expression/tests/it/sort.rs b/src/query/expression/tests/it/sort.rs index d14cf5fd59e8c..13b2afbeb4854 100644 --- a/src/query/expression/tests/it/sort.rs +++ b/src/query/expression/tests/it/sort.rs @@ -110,7 +110,7 @@ fn test_block_sort() -> Result<()> { } let decimal_block = new_block(&[ - Decimal128Type::from_data(vec![6i128, 4, 3, 2, 1, 1, 7]), + Decimal128Type::from_data_with_size(vec![6i128, 4, 3, 2, 1, 1, 7], None), StringType::from_data(vec!["b1", "b2", "b3", "b4", "b5", "b6", "b7"]), ]); @@ -127,7 +127,7 @@ fn test_block_sort() -> Result<()> { }], None, vec![ - Decimal128Type::from_data(vec![1_i128, 1, 2, 3, 4, 6, 7]), + Decimal128Type::from_data_with_size(vec![1_i128, 1, 2, 3, 4, 6, 7], None), StringType::from_data(vec!["b5", "b6", "b4", "b3", "b2", "b1", "b7"]), ], ), @@ -139,7 +139,7 @@ fn test_block_sort() -> Result<()> { }], Some(4), vec![ - Decimal128Type::from_data(vec![1_i128, 1, 2, 3]), + Decimal128Type::from_data_with_size(vec![1_i128, 1, 2, 3], None), StringType::from_data(vec!["b5", "b6", "b4", "b3"]), ], ), @@ -151,7 +151,7 @@ fn test_block_sort() -> Result<()> { }], None, vec![ - Decimal128Type::from_data(vec![7_i128, 1, 1, 2, 3, 4, 6]), + Decimal128Type::from_data_with_size(vec![7_i128, 1, 1, 2, 3, 4, 6], None), StringType::from_data(vec!["b7", "b6", "b5", "b4", "b3", "b2", "b1"]), ], ), @@ -170,7 +170,7 @@ fn test_block_sort() -> Result<()> { ], None, vec![ - Decimal128Type::from_data(vec![1_i128, 1, 2, 3, 4, 6, 7]), + Decimal128Type::from_data_with_size(vec![1_i128, 1, 2, 3, 4, 6, 7], None), StringType::from_data(vec!["b6", "b5", "b4", "b3", "b2", "b1", "b7"]), ], ), diff --git a/src/query/functions/src/aggregates/aggregate_array_agg.rs b/src/query/functions/src/aggregates/aggregate_array_agg.rs index 98f1a8919c538..06dca656f6b9b 100644 --- a/src/query/functions/src/aggregates/aggregate_array_agg.rs +++ b/src/query/functions/src/aggregates/aggregate_array_agg.rs @@ -111,6 +111,9 @@ where let val = T::upcast_scalar(value); let decimal_val = val.as_decimal().unwrap(); let new_val = match decimal_val { + DecimalScalar::Decimal64(v, _) => { + ScalarRef::Decimal(DecimalScalar::Decimal64(*v, size)) + } DecimalScalar::Decimal128(v, _) => { ScalarRef::Decimal(DecimalScalar::Decimal128(*v, size)) } @@ -215,6 +218,9 @@ where let val = T::upcast_scalar(value.clone()); let decimal_val = val.as_decimal().unwrap(); let new_val = match decimal_val { + DecimalScalar::Decimal64(v, _) => { + ScalarRef::Decimal(DecimalScalar::Decimal64(*v, size)) + } DecimalScalar::Decimal128(v, _) => { ScalarRef::Decimal(DecimalScalar::Decimal128(*v, size)) } diff --git a/src/query/functions/src/aggregates/aggregate_array_moving.rs b/src/query/functions/src/aggregates/aggregate_array_moving.rs index b4057fbe16358..273b060643e3d 100644 --- a/src/query/functions/src/aggregates/aggregate_array_moving.rs +++ b/src/query/functions/src/aggregates/aggregate_array_moving.rs @@ -33,6 +33,7 @@ use databend_common_expression::types::Float64Type; use databend_common_expression::types::Int8Type; use databend_common_expression::types::NumberDataType; use databend_common_expression::types::NumberType; +use databend_common_expression::types::ValueType; use databend_common_expression::types::F64; use databend_common_expression::utils::arithmetics_type::ResultTypeOfUnary; use databend_common_expression::with_number_mapped_type; @@ -211,12 +212,12 @@ where T: Decimal { #[inline] pub fn check_over_flow(&self, value: T) -> Result<()> { - if value > T::MAX || value < T::MIN { + if value > T::DECIMAL_MAX || value < T::DECIMAL_MIN { return Err(ErrorCode::Overflow(format!( "Decimal overflow: {} not in [{}, {}]", value, - T::MIN, - T::MAX, + T::DECIMAL_MIN, + T::DECIMAL_MAX, ))); } Ok(()) @@ -355,7 +356,7 @@ where T: Decimal sum -= self.values[i - window_size]; } let avg_val = match sum - .checked_mul(T::e(scale_add as u32)) + .checked_mul(T::e(scale_add)) .and_then(|v| v.checked_div(T::from_i128(window_size as u64))) { Some(value) => value, @@ -363,7 +364,7 @@ where T: Decimal return Err(ErrorCode::Overflow(format!( "Decimal overflow: {} mul {}", sum, - T::e(scale_add as u32) + T::e(scale_add) ))); } }; diff --git a/src/query/functions/src/aggregates/aggregate_avg.rs b/src/query/functions/src/aggregates/aggregate_avg.rs index 021a0456c0cbc..1d01645bd9d49 100644 --- a/src/query/functions/src/aggregates/aggregate_avg.rs +++ b/src/query/functions/src/aggregates/aggregate_avg.rs @@ -141,12 +141,13 @@ where fn add_internal(&mut self, count: u64, value: T::ScalarRef<'_>) -> Result<()> { self.count += count; self.value += T::to_owned_scalar(value); - if OVERFLOW && (self.value > T::Scalar::MAX || self.value < T::Scalar::MIN) { + if OVERFLOW && (self.value > T::Scalar::DECIMAL_MAX || self.value < T::Scalar::DECIMAL_MIN) + { return Err(ErrorCode::Overflow(format!( "Decimal overflow: {:?} not in [{}, {}]", self.value, - T::Scalar::MIN, - T::Scalar::MAX, + T::Scalar::DECIMAL_MIN, + T::Scalar::DECIMAL_MAX, ))); } Ok(()) @@ -185,7 +186,7 @@ where }; match self .value - .checked_mul(T::Scalar::e(decimal_avg_data.scale_add as u32)) + .checked_mul(T::Scalar::e(decimal_avg_data.scale_add)) .and_then(|v| v.checked_div(T::Scalar::from_i128(self.count))) { Some(value) => { @@ -195,7 +196,7 @@ where None => Err(ErrorCode::Overflow(format!( "Decimal overflow: {} mul {}", self.value, - T::Scalar::e(decimal_avg_data.scale_add as u32) + T::Scalar::e(decimal_avg_data.scale_add) ))), } } diff --git a/src/query/functions/src/aggregates/aggregate_distinct_state.rs b/src/query/functions/src/aggregates/aggregate_distinct_state.rs index 3bf70dfa5fc40..26d1058cd3f1c 100644 --- a/src/query/functions/src/aggregates/aggregate_distinct_state.rs +++ b/src/query/functions/src/aggregates/aggregate_distinct_state.rs @@ -33,6 +33,7 @@ use databend_common_expression::types::Buffer; use databend_common_expression::types::DataType; use databend_common_expression::types::NumberType; use databend_common_expression::types::StringType; +use databend_common_expression::types::ValueType; use databend_common_expression::Column; use databend_common_expression::ColumnBuilder; use databend_common_expression::InputColumns; diff --git a/src/query/functions/src/aggregates/aggregate_quantile_disc.rs b/src/query/functions/src/aggregates/aggregate_quantile_disc.rs index 7f77a2e66d80a..402271bee8f15 100644 --- a/src/query/functions/src/aggregates/aggregate_quantile_disc.rs +++ b/src/query/functions/src/aggregates/aggregate_quantile_disc.rs @@ -111,7 +111,7 @@ where impl UnaryState for QuantileState where - T: ArgType + Sync + Send, + T: ValueType + Sync + Send, T::Scalar: BorshSerialize + BorshDeserialize + Sync + Send + Ord, { fn add( diff --git a/src/query/functions/src/aggregates/aggregate_range_bound.rs b/src/query/functions/src/aggregates/aggregate_range_bound.rs index 2dbea10e80497..4e724c875f408 100644 --- a/src/query/functions/src/aggregates/aggregate_range_bound.rs +++ b/src/query/functions/src/aggregates/aggregate_range_bound.rs @@ -79,7 +79,7 @@ where impl UnaryState> for RangeBoundState where - T: ArgType + Sync + Send, + T: ReturnType + Sync + Send, T::Scalar: Ord + Sync + Send + BorshSerialize + BorshDeserialize, { fn add( diff --git a/src/query/functions/src/aggregates/aggregate_sum.rs b/src/query/functions/src/aggregates/aggregate_sum.rs index 896b89db30ca8..a6369777a893a 100644 --- a/src/query/functions/src/aggregates/aggregate_sum.rs +++ b/src/query/functions/src/aggregates/aggregate_sum.rs @@ -202,12 +202,14 @@ where let mut value = T::Scalar::from_u64_array(self.value); value += T::to_owned_scalar(other); - if SHOULD_CHECK_OVERFLOW && (value > T::Scalar::MAX || value < T::Scalar::MIN) { + if SHOULD_CHECK_OVERFLOW + && (value > T::Scalar::DECIMAL_MAX || value < T::Scalar::DECIMAL_MIN) + { return Err(ErrorCode::Overflow(format!( "Decimal overflow: {:?} not in [{}, {}]", value, - T::Scalar::MIN, - T::Scalar::MAX, + T::Scalar::DECIMAL_MIN, + T::Scalar::DECIMAL_MAX, ))); } self.value = value.to_u64_array(); diff --git a/src/query/functions/src/scalars/arithmetic/src/arithmetic.rs b/src/query/functions/src/scalars/arithmetic/src/arithmetic.rs index fbeb3549c29d1..f58945090f0bf 100644 --- a/src/query/functions/src/scalars/arithmetic/src/arithmetic.rs +++ b/src/query/functions/src/scalars/arithmetic/src/arithmetic.rs @@ -18,22 +18,15 @@ use std::ops::BitAnd; use std::ops::BitOr; use std::ops::BitXor; use std::str::FromStr; -use std::sync::Arc; use databend_common_expression::serialize::read_decimal_with_size; -use databend_common_expression::types::decimal::DecimalDomain; -use databend_common_expression::types::decimal::DecimalType; -use databend_common_expression::types::i256; use databend_common_expression::types::nullable::NullableColumn; use databend_common_expression::types::nullable::NullableDomain; use databend_common_expression::types::number::Number; use databend_common_expression::types::number::NumberType; use databend_common_expression::types::number::F64; use databend_common_expression::types::string::StringColumnBuilder; -use databend_common_expression::types::AnyType; use databend_common_expression::types::Bitmap; -use databend_common_expression::types::Decimal; -use databend_common_expression::types::DecimalDataType; use databend_common_expression::types::NullableType; use databend_common_expression::types::NumberClass; use databend_common_expression::types::NumberDataType; @@ -52,14 +45,8 @@ use databend_common_expression::with_integer_mapped_type; use databend_common_expression::with_number_mapped_type; use databend_common_expression::with_number_mapped_type_without_64; use databend_common_expression::with_unsigned_integer_mapped_type; -use databend_common_expression::Domain; -use databend_common_expression::EvalContext; -use databend_common_expression::Function; use databend_common_expression::FunctionDomain; -use databend_common_expression::FunctionEval; -use databend_common_expression::FunctionFactory; use databend_common_expression::FunctionRegistry; -use databend_common_expression::FunctionSignature; use databend_functions_scalar_decimal::register_decimal_to_float; use databend_functions_scalar_decimal::register_decimal_to_int; use databend_functions_scalar_decimal::register_decimal_to_string; @@ -292,86 +279,11 @@ fn register_unary_minus(registry: &mut FunctionRegistry) { ), ); } - - NumberClass::Decimal128 => { - register_decimal_minus(registry) - } - NumberClass::Decimal256 => { - // already registered in Decimal128 branch - } + NumberClass::Decimal128 | NumberClass::Decimal256 => {} }); } } -pub fn register_decimal_minus(registry: &mut FunctionRegistry) { - registry.register_function_factory("minus", FunctionFactory::Closure(Box::new(|_params, args_type| { - if args_type.len() != 1 { - return None; - } - - let is_nullable = args_type[0].is_nullable(); - let arg_type = args_type[0].remove_nullable(); - if !arg_type.is_decimal() { - return None; - } - - let function = Function { - signature: FunctionSignature { - name: "minus".to_string(), - args_type: vec![arg_type.clone()], - return_type: arg_type.clone(), - }, - eval: FunctionEval::Scalar { - calc_domain: Box::new(|_, d| match &d[0] { - Domain::Decimal(DecimalDomain::Decimal128(d, size)) => { - FunctionDomain::Domain(Domain::Decimal(DecimalDomain::Decimal128( - SimpleDomain { - min: -d.max, - max: d.min.checked_neg().unwrap_or(i128::MAX), // Only -MIN could overflow - }, - *size, - ))) - } - Domain::Decimal(DecimalDomain::Decimal256(d, size)) => { - FunctionDomain::Domain(Domain::Decimal(DecimalDomain::Decimal256( - SimpleDomain { - min: -d.max, - max: d.min.checked_neg().unwrap_or(i256::MAX), // Only -MIN could overflow - }, - *size, - ))) - } - _ => unreachable!(), - }), - eval: Box::new(unary_minus_decimal), - }, - }; - - if is_nullable { - Some(Arc::new(function.passthrough_nullable())) - } else { - Some(Arc::new(function)) - } - }))); -} - -fn unary_minus_decimal(args: &[Value], ctx: &mut EvalContext) -> Value { - let arg = &args[0]; - let (decimal, _) = DecimalDataType::from_value(arg).unwrap(); - match decimal { - DecimalDataType::Decimal128(size) => { - let arg = arg.try_downcast().unwrap(); - type T = DecimalType; - vectorize_1_arg::(|t, _| -t)(arg, ctx).upcast_decimal(size) - } - DecimalDataType::Decimal256(size) => { - let arg = arg.try_downcast().unwrap(); - type T = DecimalType; - vectorize_1_arg::(|t, _| -t)(arg, ctx).upcast_decimal(size) - } - } -} - #[inline] fn parse_number( s: &str, diff --git a/src/query/functions/src/scalars/decimal/src/arithmetic.rs b/src/query/functions/src/scalars/decimal/src/arithmetic.rs index d7f7107bcdfcc..39749dabcd5fa 100644 --- a/src/query/functions/src/scalars/decimal/src/arithmetic.rs +++ b/src/query/functions/src/scalars/decimal/src/arithmetic.rs @@ -15,11 +15,15 @@ use std::ops::*; use std::sync::Arc; +use databend_common_expression::types::compute_view::Compute; +use databend_common_expression::types::compute_view::ComputeView; use databend_common_expression::types::decimal::*; -use databend_common_expression::types::i256; +use databend_common_expression::types::SimpleDomain; use databend_common_expression::types::*; +use databend_common_expression::vectorize_1_arg; use databend_common_expression::vectorize_2_arg; use databend_common_expression::vectorize_with_builder_2_arg; +use databend_common_expression::with_decimal_mapped_type; use databend_common_expression::Domain; use databend_common_expression::EvalContext; use databend_common_expression::Function; @@ -30,8 +34,9 @@ use databend_common_expression::FunctionRegistry; use databend_common_expression::FunctionSignature; use databend_common_expression::Value; -use super::convert_to_decimal; use super::convert_to_decimal_domain; +use crate::decimal_to_decimal_fast; +use crate::other_to_decimal; #[derive(Copy, Clone, Debug)] enum ArithmeticOp { @@ -76,17 +81,17 @@ impl ArithmeticOp { b: &DecimalSize, ) -> Option<(DecimalSize, DecimalSize, DecimalSize)> { // from snowflake: https://docs.snowflake.com/sql-reference/operators-arithmetic - let (mut precision, scale) = match self { + let (precision, scale) = match self { ArithmeticOp::Multiply => { let scale = (a.scale() + b.scale()).min(a.scale().max(b.scale()).max(12)); - let l = a.leading_digits() + b.leading_digits(); - (l + scale, scale) + let leading = a.leading_digits() + b.leading_digits(); + (leading + scale, scale) } ArithmeticOp::Divide => { let scale = a.scale().max((a.scale() + 6).min(12)); // scale must be >= a.sale() - let l = a.leading_digits() + b.scale(); // l must be >= a.leading_digits() - (l + scale, scale) // so precision must be >= a.precision() + let leading = a.leading_digits() + b.scale(); // leading must be >= a.leading_digits() + (leading + scale, scale) // so precision must be >= a.precision() } ArithmeticOp::Plus | ArithmeticOp::Minus => { @@ -98,15 +103,13 @@ impl ArithmeticOp { }; // if the args both are Decimal128, we need to clamp the precision to 38 - if a.precision() <= MAX_DECIMAL128_PRECISION && b.precision() <= MAX_DECIMAL128_PRECISION { - precision = precision.min(MAX_DECIMAL128_PRECISION); - } else if precision <= MAX_DECIMAL128_PRECISION - && DecimalDataType::belong_diff_precision(a.precision(), b.precision()) + let precision = if a.precision() <= MAX_DECIMAL128_PRECISION + && b.precision() <= MAX_DECIMAL128_PRECISION { - // lift up to decimal256 - precision = MAX_DECIMAL128_PRECISION + 1; - } - precision = precision.min(MAX_DECIMAL256_PRECISION); + precision.min(MAX_DECIMAL128_PRECISION) + } else { + precision.min(MAX_DECIMAL256_PRECISION) + }; let result_type = DecimalSize::new(precision, scale).ok()?; match self { @@ -125,45 +128,89 @@ impl ArithmeticOp { )) } - ArithmeticOp::Plus | ArithmeticOp::Minus => { - Some((result_type, result_type, result_type)) - } + ArithmeticOp::Plus | ArithmeticOp::Minus => Some(( + if scale == a.scale() { + *a + } else { + DecimalSize::new(a.precision(), scale).ok()? + }, + if scale == b.scale() { + *b + } else { + DecimalSize::new(b.precision(), scale).ok()? + }, + result_type, + )), } } } +fn convert_to_decimal( + value: &Value, + data_type: &DataType, + size: DecimalSize, + ctx: &mut EvalContext, +) -> ((Value, DecimalSize), DecimalDataType) { + if data_type.is_decimal() { + let (value_decimal, value_type) = decimal_to_decimal_fast(value, ctx, size); + ((value_decimal, size), value_type) + } else { + let value_type = size.best_type(); + let value_decimal = other_to_decimal(value, ctx, data_type, value_type); + ((value_decimal, size), value_type) + } +} + fn op_decimal( - a: &Value, - b: &Value, + a: (&Value, &DataType, DecimalSize), + b: (&Value, &DataType, DecimalSize), ctx: &mut EvalContext, - left: DecimalDataType, - right: DecimalDataType, result_type: DecimalDataType, op: ArithmeticOp, ) -> Value { - match left { - DecimalDataType::Decimal128(_) => { - binary_decimal::(a, b, ctx, left, right, result_type.size(), op) - } - DecimalDataType::Decimal256(_) => { - binary_decimal::(a, b, ctx, left, right, result_type.size(), op) + let (a, a_type) = convert_to_decimal(a.0, a.1, a.2, ctx); + let (b, b_type) = convert_to_decimal(b.0, b.1, b.2, ctx); + + with_decimal_mapped_type!(|T| match result_type.size().best_type() { + DecimalDataType::T(_) => { + with_decimal_mapped_type!(|A| match a_type { + DecimalDataType::A(_) => { + with_decimal_mapped_type!(|B| match b_type { + DecimalDataType::B(_) => { + with_decimal_mapped_type!(|OUT| match result_type { + DecimalDataType::OUT(size) => { + binary_decimal::< + DecimalConvert, + ComputeView, _, _>, + ComputeView, _, _>, + _, + _, + >(a, b, ctx, size, op) + } + }) + } + }) + } + }) } - } + }) } -fn binary_decimal( - a: &Value, - b: &Value, +fn binary_decimal( + (a, a_size): (Value, DecimalSize), + (b, b_size): (Value, DecimalSize), ctx: &mut EvalContext, - left: DecimalDataType, - right: DecimalDataType, - size: DecimalSize, + return_size: DecimalSize, op: ArithmeticOp, ) -> Value where T: Decimal + Add + Sub + Mul, + U: Decimal, + C: Compute, CoreDecimal>, + L: for<'a> AccessType = T>, + R: for<'a> AccessType = T>, { - let overflow = size.precision() == T::default_decimal_size().precision(); + let overflow = return_size.precision() == T::default_decimal_size().precision(); let a = a.try_downcast().unwrap(); let b = b.try_downcast().unwrap(); @@ -171,14 +218,14 @@ where let zero = T::zero(); let one = T::one(); - let result = match op { + match op { ArithmeticOp::Divide => { - let scale_a = left.scale(); - let scale_b = right.scale(); + let scale_a = a_size.scale(); + let scale_b = b_size.scale(); // Note: the result scale is always larger than the left scale - let scale_mul = (scale_b + size.scale() - scale_a) as u32; - let func = |a: T, b: T, result: &mut Vec, ctx: &mut EvalContext| { + let scale_mul = (scale_b + return_size.scale() - scale_a) as u32; + let func = |a: T, b: T, result: &mut Vec, ctx: &mut EvalContext| { // We are using round div here which follow snowflake's behavior: https://docs.snowflake.com/sql-reference/operators-arithmetic // For example: // round_div(5, 2) --> 3 @@ -187,61 +234,58 @@ where // round_div(-5, -2) --> 3 if std::intrinsics::unlikely(b == zero) { ctx.set_error(result.len(), "divided by zero"); - result.push(one); + result.push(C::compute(&one)); } else { match a.do_round_div(b, scale_mul) { - Some(t) => result.push(t), + Some(t) => result.push(C::compute(&t)), None => { ctx.set_error( result.len(), concat!("Decimal div overflow at line : ", line!()), ); - result.push(one); + result.push(C::compute(&one)); } } } }; - vectorize_with_builder_2_arg::, DecimalType, DecimalType>(func)( - a, b, ctx, - ) + vectorize_with_builder_2_arg::>(func)(a, b, ctx) } ArithmeticOp::Multiply => { - let scale_a = left.scale(); - let scale_b = right.scale(); + let scale_a = a_size.scale(); + let scale_b = b_size.scale(); - let scale_mul = scale_a + scale_b - size.scale(); + let scale_mul = scale_a + scale_b - return_size.scale(); if scale_mul == 0 { - let func = |a: T, b: T, _ctx: &mut EvalContext| op.calc(a, b); - vectorize_2_arg::, DecimalType, DecimalType>(func)(a, b, ctx) + vectorize_2_arg::>(|a, b, _| C::compute(&op.calc(a, b)))( + a, b, ctx, + ) } else { - let func = |a: T, b: T, result: &mut Vec, ctx: &mut EvalContext| match a + let func = |a: T, b: T, result: &mut Vec, ctx: &mut EvalContext| match a .do_round_mul(b, scale_mul as u32, overflow) { - Some(t) => result.push(t), + Some(t) => result.push(C::compute(&t)), None => { ctx.set_error( result.len(), concat!("Decimal multiply overflow at line : ", line!()), ); - result.push(one); + result.push(C::compute(&one)); } }; - vectorize_with_builder_2_arg::, DecimalType, DecimalType>(func)( - a, b, ctx, - ) + vectorize_with_builder_2_arg::>(func)(a, b, ctx) } } ArithmeticOp::Plus | ArithmeticOp::Minus => { if overflow { - let min_for_precision = T::min_for_precision(size.precision()); - let max_for_precision = T::max_for_precision(size.precision()); + let min_for_precision = T::min_for_precision(return_size.precision()); + let max_for_precision = T::max_for_precision(return_size.precision()); - let func = |a: T, b: T, result: &mut Vec, ctx: &mut EvalContext| { + let func = |a: T, b: T, result: &mut Vec, ctx: &mut EvalContext| { let t = op.calc(a, b); if t < min_for_precision || t > max_for_precision { @@ -249,24 +293,21 @@ where result.len(), concat!("Decimal overflow at line : ", line!()), ); - result.push(one); + result.push(C::compute(&one)); } else { - result.push(t); + result.push(C::compute(&t)); } }; - vectorize_with_builder_2_arg::, DecimalType, DecimalType>(func)( + vectorize_with_builder_2_arg::>(func)(a, b, ctx) + } else { + vectorize_2_arg::>(|l, r, _| C::compute(&op.calc(l, r)))( a, b, ctx, ) - } else { - let func = |l: T, r: T, _ctx: &mut EvalContext| op.calc(l, r); - - vectorize_2_arg::, DecimalType, DecimalType>(func)(a, b, ctx) } } - }; - - result.upcast_decimal(size) + } + .upcast_decimal(return_size) } #[inline(always)] @@ -361,26 +402,32 @@ fn register_decimal_binary_op(registry: &mut FunctionRegistry, arithmetic_op: Ar return None; } - let decimal_a = DecimalDataType::from_size(args_type[0].get_decimal_properties()?).unwrap(); - let decimal_b = DecimalDataType::from_size(args_type[1].get_decimal_properties()?).unwrap(); + let decimal_a = args_type[0].get_decimal_properties()?; + let decimal_b = args_type[1].get_decimal_properties()?; - // left, right will unify to same width decimal, both 256 or both 128 - let (left, right, return_decimal_type) = - arithmetic_op.result_size(&decimal_a.size(), &decimal_b.size())?; - let (left, right, return_decimal_type) = ( - DecimalDataType::from_size(left).unwrap(), - DecimalDataType::from_size(right).unwrap(), - DecimalDataType::from_size(return_decimal_type).unwrap(), - ); + let (left_size, right_size, return_size) = + arithmetic_op.result_size(&decimal_a, &decimal_b)?; let function = Function { signature: FunctionSignature { name: format!("{:?}", arithmetic_op).to_lowercase(), args_type: args_type.clone(), - return_type: DataType::Decimal(return_decimal_type.size()), + return_type: DataType::Decimal(return_size), }, eval: FunctionEval::Scalar { calc_domain: Box::new(move |ctx, d| { + let (left, right) = + if left_size.can_carried_by_128() && right_size.can_carried_by_128() { + ( + DecimalDataType::Decimal128(left_size), + DecimalDataType::Decimal128(right_size), + ) + } else { + ( + DecimalDataType::Decimal256(left_size), + DecimalDataType::Decimal256(right_size), + ) + }; let lhs = convert_to_decimal_domain(ctx, d[0].clone(), left); let rhs = convert_to_decimal_domain(ctx, d[1].clone(), right); @@ -389,7 +436,7 @@ fn register_decimal_binary_op(registry: &mut FunctionRegistry, arithmetic_op: Ar _ => return FunctionDomain::Full, }; - let size = return_decimal_type.size(); + let size = return_size; let default_domain = if matches!(arithmetic_op, ArithmeticOp::Divide) { FunctionDomain::MayThrow @@ -419,10 +466,20 @@ fn register_decimal_binary_op(registry: &mut FunctionRegistry, arithmetic_op: Ar .unwrap_or(default_domain) }), eval: Box::new(move |args, ctx| { - let a = convert_to_decimal(&args[0], ctx, &args_type[0], left); - let b = convert_to_decimal(&args[1], ctx, &args_type[1], right); + let return_decimal_type = if !ctx.strict_eval && return_size.can_carried_by_64() + { + DecimalDataType::Decimal64(return_size) + } else { + DecimalDataType::from(return_size) + }; - op_decimal(&a, &b, ctx, left, right, return_decimal_type, arithmetic_op) + op_decimal( + (&args[0], &args_type[0], left_size), + (&args[1], &args_type[1], right_size), + ctx, + return_decimal_type, + arithmetic_op, + ) }), }, }; @@ -436,6 +493,95 @@ fn register_decimal_binary_op(registry: &mut FunctionRegistry, arithmetic_op: Ar registry.register_function_factory(&name, factory); } +pub fn register_decimal_minus(registry: &mut FunctionRegistry) { + registry.register_function_factory("minus", FunctionFactory::Closure(Box::new(|_params, args_type| { + if args_type.len() != 1 { + return None; + } + + let is_nullable = args_type[0].is_nullable(); + let arg_type = args_type[0].remove_nullable(); + if !arg_type.is_decimal() { + return None; + } + + let function = Function { + signature: FunctionSignature { + name: "minus".to_string(), + args_type: vec![arg_type.clone()], + return_type: arg_type.clone(), + }, + eval: FunctionEval::Scalar { + calc_domain: Box::new(|_, d| match &d[0] { + Domain::Decimal(DecimalDomain::Decimal64(d, size)) => { + FunctionDomain::Domain(Domain::Decimal(DecimalDomain::Decimal64( + SimpleDomain { + min: -d.max, + max: d.min.checked_neg().unwrap_or(i64::DECIMAL_MAX), // Only -MIN could overflow + }, + *size, + ))) + } + Domain::Decimal(DecimalDomain::Decimal128(d, size)) => { + FunctionDomain::Domain(Domain::Decimal(DecimalDomain::Decimal128( + SimpleDomain { + min: -d.max, + max: d.min.checked_neg().unwrap_or(i128::DECIMAL_MAX), // Only -MIN could overflow + }, + *size, + ))) + } + Domain::Decimal(DecimalDomain::Decimal256(d, size)) => { + FunctionDomain::Domain(Domain::Decimal(DecimalDomain::Decimal256( + SimpleDomain { + min: -d.max, + max: d.min.checked_neg().unwrap_or(i256::DECIMAL_MAX), // Only -MIN could overflow + }, + *size, + ))) + } + _ => unreachable!(), + }), + eval: Box::new(unary_minus_decimal), + }, + }; + + if is_nullable { + Some(Arc::new(function.passthrough_nullable())) + } else { + Some(Arc::new(function)) + } + }))); +} + +fn unary_minus_decimal(args: &[Value], ctx: &mut EvalContext) -> Value { + let arg = &args[0]; + let (decimal, _) = DecimalDataType::from_value(arg).unwrap(); + match decimal { + DecimalDataType::Decimal64(size) => { + if ctx.strict_eval { + let arg = arg.try_downcast().unwrap(); + vectorize_1_arg::(|t, _| -t)(arg, ctx) + .upcast_decimal(size) + } else { + let arg = arg.try_downcast().unwrap(); + type T = DecimalType; + vectorize_1_arg::(|t, _| -t)(arg, ctx).upcast_decimal(size) + } + } + DecimalDataType::Decimal128(size) => { + let arg = arg.try_downcast().unwrap(); + type T = DecimalType; + vectorize_1_arg::(|t, _| -t)(arg, ctx).upcast_decimal(size) + } + DecimalDataType::Decimal256(size) => { + let arg = arg.try_downcast().unwrap(); + type T = DecimalType; + vectorize_1_arg::(|t, _| -t)(arg, ctx).upcast_decimal(size) + } + } +} + pub fn register_decimal_arithmetic(registry: &mut FunctionRegistry) { // TODO checked overflow by default register_decimal_binary_op(registry, ArithmeticOp::Plus); diff --git a/src/query/functions/src/scalars/decimal/src/cast.rs b/src/query/functions/src/scalars/decimal/src/cast.rs index 187c749c3658b..748bda06a1293 100644 --- a/src/query/functions/src/scalars/decimal/src/cast.rs +++ b/src/query/functions/src/scalars/decimal/src/cast.rs @@ -12,18 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::cmp::Ordering; use std::ops::Div; use std::ops::Mul; use std::sync::Arc; use databend_common_base::base::OrderedFloat; use databend_common_expression::serialize::read_decimal_with_size; +use databend_common_expression::types::compute_view::Compute; use databend_common_expression::types::decimal::*; use databend_common_expression::types::i256; use databend_common_expression::types::*; use databend_common_expression::vectorize_1_arg; use databend_common_expression::vectorize_with_builder_1_arg; use databend_common_expression::with_decimal_mapped_type; +use databend_common_expression::with_decimal_type; use databend_common_expression::with_integer_mapped_type; use databend_common_expression::with_number_mapped_type; use databend_common_expression::DataBlock; @@ -46,10 +49,7 @@ use crate::cast_from_jsonb::variant_to_decimal; // int float to decimal pub fn register_to_decimal(registry: &mut FunctionRegistry) { let factory = |params: &[Scalar], args_type: &[DataType]| { - if args_type.len() != 1 { - return None; - } - if params.len() != 2 { + if args_type.len() != 1 || params.len() != 2 { return None; } @@ -67,13 +67,12 @@ pub fn register_to_decimal(registry: &mut FunctionRegistry) { } let decimal_size = - DecimalSize::new_unchecked(params[0].get_i64()? as _, params[1].get_i64()? as _); - let decimal_type = DecimalDataType::from_size(decimal_size).ok()?; + DecimalSize::new(params[0].get_i64()? as _, params[1].get_i64()? as _).ok()?; let return_type = if from_type == DataType::Variant { - DataType::Nullable(Box::new(DataType::Decimal(decimal_type.size()))) + DataType::Nullable(Box::new(DataType::Decimal(decimal_size))) } else { - DataType::Decimal(decimal_type.size()) + DataType::Decimal(decimal_size) }; Some(Function { signature: FunctionSignature { @@ -83,12 +82,18 @@ pub fn register_to_decimal(registry: &mut FunctionRegistry) { }, eval: FunctionEval::Scalar { calc_domain: Box::new(move |ctx, d| { + let decimal_type = DecimalDataType::from(decimal_size); convert_to_decimal_domain(ctx, d[0].clone(), decimal_type) .map(|d| FunctionDomain::Domain(Domain::Decimal(d))) .unwrap_or(FunctionDomain::MayThrow) }), eval: Box::new(move |args, ctx| { - convert_to_decimal(&args[0], ctx, &from_type, decimal_type) + let desc_type = if decimal_size.can_carried_by_64() && !ctx.strict_eval { + DecimalDataType::Decimal64(decimal_size) + } else { + DecimalDataType::from(decimal_size) + }; + convert_to_decimal(&args[0], ctx, &from_type, desc_type) }), }, }) @@ -142,7 +147,7 @@ pub fn register_to_decimal(registry: &mut FunctionRegistry) { 0 }; let decimal_size = DecimalSize::new(precision, scale).ok()?; - let decimal_type = DecimalDataType::from_size(decimal_size).ok()?; + let decimal_type = DecimalDataType::from(decimal_size); Some(Arc::new(Function { signature: FunctionSignature { @@ -205,14 +210,12 @@ pub fn register_decimal_to_float(registry: &mut FunctionRegistry) { }; let eval = if is_f32 { - let arg_type = arg_type.clone(); Box::new(move |args: &[Value], tx: &mut EvalContext| { - decimal_to_float::(&args[0], arg_type.clone(), tx) + decimal_to_float::(&args[0], tx) }) as _ } else { - let arg_type = arg_type.clone(); Box::new(move |args: &[Value], tx: &mut EvalContext| { - decimal_to_float::(&args[0], arg_type.clone(), tx) + decimal_to_float::(&args[0], tx) }) as _ }; @@ -292,6 +295,10 @@ pub fn register_decimal_to_int(registry: &mut FunctionRegistry) { eval: FunctionEval::Scalar { calc_domain: Box::new(|ctx, d| { let res_fn = move || match d[0].as_decimal().unwrap() { + DecimalDomain::Decimal64(d, size) => Some(SimpleDomain:: { + min: d.min.to_int(size.scale(), ctx.rounding_mode)?, + max: d.max.to_int(size.scale(), ctx.rounding_mode)?, + }), DecimalDomain::Decimal128(d, size) => Some(SimpleDomain:: { min: d.min.to_int(size.scale(), ctx.rounding_mode)?, max: d.max.to_int(size.scale(), ctx.rounding_mode)?, @@ -306,7 +313,7 @@ pub fn register_decimal_to_int(registry: &mut FunctionRegistry) { .map(|d| FunctionDomain::Domain(Domain::Number(T::upcast_domain(d)))) .unwrap_or(FunctionDomain::MayThrow) }), - eval: Box::new(move |args, tx| decimal_to_int::(&args[0], arg_type.clone(), tx)), + eval: Box::new(move |args, ctx| decimal_to_int::(&args[0], ctx)), }, }; @@ -390,7 +397,7 @@ fn decimal_to_string( ctx: &mut EvalContext, ) -> Value { let scale = from_type.scale(); - vectorize_1_arg::, StringType>(|v, _| v.display(scale))(arg, ctx) + vectorize_1_arg::, StringType>(|v, _| v.to_decimal_string(scale))(arg, ctx) } pub fn convert_to_decimal( @@ -401,17 +408,37 @@ pub fn convert_to_decimal( ) -> Value { if from_type.is_decimal() { let (from_type, _) = DecimalDataType::from_value(arg).unwrap(); - return decimal_to_decimal(arg, ctx, from_type, dest_type); + decimal_to_decimal(arg, ctx, from_type, dest_type) + } else { + other_to_decimal(arg, ctx, from_type, dest_type) + } +} + +pub fn other_to_decimal( + arg: &Value, + ctx: &mut EvalContext, + from_type: &DataType, + dest_type: DecimalDataType, +) -> Value { + if let Some(v) = try { + let size = dest_type.as_decimal64()?; + if size.scale() != 0 || size.precision() < 19 { + None? + } + let buffer = arg.as_column()?.as_number()?.as_int64()?; + Value::::Column(buffer.clone()).upcast_decimal(*size) + } { + return v; } with_decimal_mapped_type!(|DECIMAL_TYPE| match dest_type { DecimalDataType::DECIMAL_TYPE(_) => { - other_to_decimal::(arg, ctx, from_type, dest_type) + other_to_decimal_type::(arg, ctx, from_type, dest_type) } }) } -pub fn other_to_decimal( +fn other_to_decimal_type( arg: &Value, ctx: &mut EvalContext, from_type: &DataType, @@ -421,12 +448,12 @@ where T: Decimal + Mul + Div, { let size = dest_type.size(); - let result = match from_type { + match from_type { DataType::Boolean => { let arg = arg.try_downcast().unwrap(); vectorize_1_arg::>(|a: bool, _| { if a { - T::e(size.scale() as u32) + T::e(size.scale()) } else { T::zero() } @@ -466,8 +493,8 @@ where return result.upcast_decimal(size); } _ => unreachable!("to_decimal not support this DataType"), - }; - result.upcast_decimal(size) + } + .upcast_decimal(size) } fn convert_as_decimal( @@ -512,7 +539,7 @@ pub fn convert_to_decimal_domain( DecimalDomain::DECIMAL(d, size) => { let min = d.min; let max = d.max; - DecimalType::from_data_with_size(vec![min, max], size) + DecimalType::from_data_with_size(vec![min, max], Some(size)) } }) } @@ -546,18 +573,14 @@ pub fn convert_to_decimal_domain( let decimal_col = res.as_column()?.as_decimal()?; assert_eq!(decimal_col.len(), 2); - Some(match decimal_col { - DecimalColumn::Decimal128(buf, size) => { + let domain = with_decimal_type!(|DECIMAL| match decimal_col { + DecimalColumn::DECIMAL(buf, size) => { assert_eq!(&dest_size, size); let (min, max) = unsafe { (*buf.get_unchecked(0), *buf.get_unchecked(1)) }; - DecimalDomain::Decimal128(SimpleDomain { min, max }, *size) + DecimalDomain::DECIMAL(SimpleDomain { min, max }, *size) } - DecimalColumn::Decimal256(buf, size) => { - assert_eq!(&dest_size, size); - let (min, max) = unsafe { (*buf.get_unchecked(0), *buf.get_unchecked(1)) }; - DecimalDomain::Decimal256(SimpleDomain { min, max }, *size) - } - }) + }); + Some(domain) } fn string_to_decimal( @@ -595,30 +618,29 @@ where S: AccessType, for<'a> S::ScalarRef<'a>: Number + AsPrimitive, { - let multiplier = T::e(size.scale() as u32); + let multiplier = T::e(size.scale()); let min_for_precision = T::min_for_precision(size.precision()); let max_for_precision = T::max_for_precision(size.precision()); - let mut never_overflow = true; - - for x in [ - as Number>::MIN, - as Number>::MAX, - ] { - if let Some(x) = T::from_i128(x.as_()).checked_mul(multiplier) { - if x > max_for_precision || x < min_for_precision { - never_overflow = false; - break; - } - } else { - never_overflow = false; - break; - } - } + + let never_overflow = if size.scale() == 0 { + true + } else { + [ + as Number>::MIN, + as Number>::MAX, + ] + .into_iter() + .all(|x| { + let Some(x) = T::from_i128(x.as_()).checked_mul(multiplier) else { + return false; + }; + x >= min_for_precision && x <= max_for_precision + }) + }; if never_overflow { - let f = |x: S::ScalarRef<'_>, _ctx: &mut EvalContext| T::from_i128(x.as_()) * multiplier; - vectorize_1_arg(f)(from, ctx) + vectorize_1_arg(|x: S::ScalarRef<'_>, _| T::from_i128(x.as_()) * multiplier)(from, ctx) } else { let f = |x: S::ScalarRef<'_>, builder: &mut Vec, ctx: &mut EvalContext| { if let Some(x) = T::from_i128(x.as_()).checked_mul(multiplier) { @@ -677,80 +699,120 @@ where } #[inline] -pub(super) fn get_round_val(x: T, scale: u32, rounding_mode: bool) -> Option { - let mut round_val = None; - if rounding_mode && scale > 0 { - // Checking whether numbers need to be added or subtracted to calculate rounding - if let Some(r) = x.checked_rem(T::e(scale)) { - if let Some(m) = r.checked_div(T::e(scale - 1)) { - if m >= T::from_i128(5i64) { - round_val = Some(T::one()); - } else if m <= T::from_i128(-5i64) { - round_val = Some(T::minus_one()); - } - } - } +pub(super) fn get_round_val(x: T, scale: u8, rounding_mode: bool) -> Option { + if !rounding_mode || scale == 0 { + return None; } - round_val + // Checking whether numbers need to be added or subtracted to calculate rounding + let q = x.checked_div(T::e(scale - 1))?; + let m = q.checked_rem(T::from_i128(10))?; + if m >= T::from_i128(5) { + return Some(T::one()); + } + if m <= T::from_i128(-5) { + return Some(T::minus_one()); + } + None } -fn decimal_256_to_128( +fn decimal_shrink_cast( from_size: DecimalSize, dest_size: DecimalSize, - buffer: Value>, + buffer: Value>, ctx: &mut EvalContext, -) -> Value> { - let max = i128::max_for_precision(dest_size.precision()); - let min = i128::min_for_precision(dest_size.precision()); - - if dest_size.scale() >= from_size.scale() { - let factor = i256::e((dest_size.scale() - from_size.scale()) as u32); +) -> Value> +where + F: Decimal + Copy, + T: Decimal + Copy, + C: Compute, CoreDecimal>, +{ + let max = F::max_for_precision(dest_size.precision()); + let min = F::min_for_precision(dest_size.precision()); - vectorize_with_builder_1_arg::, DecimalType>( - |x: i256, builder: &mut Vec, ctx: &mut EvalContext| match x.checked_mul(factor) { - Some(x) if x <= max && x >= min => builder.push(*x.low()), - _ => { + match dest_size.scale().cmp(&from_size.scale()) { + Ordering::Equal => vectorize_with_builder_1_arg::, DecimalType>( + |x: F, builder: &mut Vec, ctx: &mut EvalContext| { + if x <= max && x >= min { + builder.push(C::compute(&x)); + } else { ctx.set_error( builder.len(), concat!("Decimal overflow at line : ", line!()), ); - builder.push(i128::one()); + builder.push(T::one()); } }, - )(buffer, ctx) - } else { - let scale_diff = (from_size.scale() - dest_size.scale()) as u32; - let factor = i256::e(scale_diff); - let source_factor = i256::e(from_size.scale() as u32); - - vectorize_with_builder_1_arg::, DecimalType>( - |x: i256, builder: &mut Vec, ctx: &mut EvalContext| { - let round_val = get_round_val::(x, scale_diff, ctx.func_ctx.rounding_mode); - let y = match (x.checked_div(factor), round_val) { - (Some(x), Some(round_val)) => x.checked_add(round_val), - (Some(x), None) => Some(x), - (None, _) => None, - }; - - match y { - Some(y) if (y <= max && y >= min) && (y != 0 || x / source_factor == 0) => { - builder.push(*y.low()); + )(buffer, ctx), + Ordering::Greater => { + let factor = F::e(dest_size.scale() - from_size.scale()); + + vectorize_with_builder_1_arg::, DecimalType>( + |x: F, builder: &mut Vec, ctx: &mut EvalContext| match x.checked_mul(factor) { + Some(x) if x <= max && x >= min => { + builder.push(C::compute(&x)); } _ => { ctx.set_error( builder.len(), concat!("Decimal overflow at line : ", line!()), ); - - builder.push(i128::one()); + builder.push(T::one()); } - } - }, - )(buffer, ctx) + }, + )(buffer, ctx) + } + Ordering::Less => { + let scale_diff = from_size.scale() - dest_size.scale(); + let factor = F::e(scale_diff); + let scale = from_size.scale(); + + vectorize_with_builder_1_arg::, DecimalType>( + |x: F, builder: &mut Vec, ctx: &mut EvalContext| match decimal_scale_reduction( + x, + min, + max, + factor, + scale, + scale_diff, + ctx.func_ctx.rounding_mode, + ) { + Some(y) => builder.push(C::compute(&y)), + None => { + ctx.set_error( + builder.len(), + format!("Decimal overflow at line : {}", line!()), + ); + builder.push(T::one()); + } + }, + )(buffer, ctx) + } } } -fn decimal_to_decimal_typed( +pub(super) fn decimal_scale_reduction( + x: T, + min: T, + max: T, + factor: T, + scale: u8, + scale_diff: u8, + rounding_mode: bool, +) -> Option { + let q = x.checked_div(factor)?; + let y = if let Some(round_val) = get_round_val(x, scale_diff, rounding_mode) { + q.checked_add(round_val)? + } else { + q + }; + if y > max || y < min || y == T::zero() && !x.int_part_is_zero(scale) { + None + } else { + Some(y) + } +} + +fn decimal_expand_cast( from_size: DecimalSize, dest_size: DecimalSize, buffer: Value>, @@ -758,7 +820,7 @@ fn decimal_to_decimal_typed( ) -> Value> where F: Decimal, - T: Decimal + From + Div, + T: Decimal + From, { // faster path if from_size.scale() == dest_size.scale() && from_size.precision() <= dest_size.precision() { @@ -774,40 +836,35 @@ where } if from_size.scale() > dest_size.scale() { - let scale_diff = (from_size.scale() - dest_size.scale()) as u32; + let scale_diff = from_size.scale() - dest_size.scale(); let factor = T::e(scale_diff); let max = T::max_for_precision(dest_size.precision()); let min = T::min_for_precision(dest_size.precision()); - let source_factor = T::e(from_size.scale() as u32); - vectorize_with_builder_1_arg::, DecimalType>( - |x: F, builder: &mut Vec, ctx: &mut EvalContext| { - let x = T::from(x); - let round_val = get_round_val::(x, scale_diff, ctx.func_ctx.rounding_mode); - let y = match (x.checked_div(factor), round_val) { - (Some(x), Some(round_val)) => x.checked_add(round_val), - (Some(x), None) => Some(x), - (None, _) => None, - }; - - let z = T::zero(); - match y { - Some(y) if y <= max && y >= min && (y != z || x / source_factor == z) => { - builder.push(y as T); - } - _ => { - ctx.set_error( - builder.len(), - concat!("Decimal overflow at line : ", line!()), - ); - builder.push(T::one()); - } + |x: F, builder: &mut Vec, ctx: &mut EvalContext| match decimal_scale_reduction( + T::from(x), + min, + max, + factor, + from_size.scale(), + scale_diff, + ctx.func_ctx.rounding_mode, + ) { + Some(y) => { + builder.push(y as T); + } + _ => { + ctx.set_error( + builder.len(), + concat!("Decimal overflow at line : ", line!()), + ); + builder.push(T::one()); } }, )(buffer, ctx) } else { - let factor = T::e((dest_size.scale() - from_size.scale()) as u32); + let factor = T::e(dest_size.scale() - from_size.scale()); let min = T::min_for_precision(dest_size.precision()); let max = T::max_for_precision(dest_size.precision()); @@ -839,29 +896,68 @@ pub fn decimal_to_decimal( ) -> Value { let from_size = from_type.size(); let dest_size = dest_type.size(); - match (from_type, dest_type) { - (DecimalDataType::Decimal128(_), DecimalDataType::Decimal128(_)) => { - let value = arg.try_downcast().unwrap(); - decimal_to_decimal_typed::(from_size, dest_size, value, ctx) - .upcast_decimal(dest_size) - } - (DecimalDataType::Decimal128(_), DecimalDataType::Decimal256(_)) => { + match from_type { + DecimalDataType::Decimal64(_) => { let value = arg.try_downcast().unwrap(); - decimal_to_decimal_typed::(from_size, dest_size, value, ctx) - .upcast_decimal(dest_size) + with_decimal_mapped_type!(|OUT| match dest_type { + DecimalDataType::OUT(_) => { + decimal_expand_cast::(from_size, dest_size, value, ctx) + .upcast_decimal(dest_size) + } + }) } - (DecimalDataType::Decimal256(_), DecimalDataType::Decimal128(_)) => { + DecimalDataType::Decimal128(_) => { let value = arg.try_downcast().unwrap(); - decimal_256_to_128(from_size, dest_size, value, ctx).upcast_decimal(dest_size) + match dest_type { + DecimalDataType::Decimal64(_) => { + decimal_shrink_cast::(from_size, dest_size, value, ctx) + .upcast_decimal(dest_size) + } + DecimalDataType::Decimal128(_) => { + decimal_expand_cast::(from_size, dest_size, value, ctx) + .upcast_decimal(dest_size) + } + DecimalDataType::Decimal256(_) => { + decimal_expand_cast::(from_size, dest_size, value, ctx) + .upcast_decimal(dest_size) + } + } } - (DecimalDataType::Decimal256(_), DecimalDataType::Decimal256(_)) => { + DecimalDataType::Decimal256(_) => { let value = arg.try_downcast().unwrap(); - decimal_to_decimal_typed::(from_size, dest_size, value, ctx) - .upcast_decimal(dest_size) + match dest_type { + DecimalDataType::Decimal64(_) => { + decimal_shrink_cast::(from_size, dest_size, value, ctx) + .upcast_decimal(dest_size) + } + DecimalDataType::Decimal128(_) => { + decimal_shrink_cast::(from_size, dest_size, value, ctx) + .upcast_decimal(dest_size) + } + DecimalDataType::Decimal256(_) => { + decimal_expand_cast::(from_size, dest_size, value, ctx) + .upcast_decimal(dest_size) + } + } } } } +pub fn decimal_to_decimal_fast( + arg: &Value, + ctx: &mut EvalContext, + size: DecimalSize, +) -> (Value, DecimalDataType) { + let (from_type, _) = DecimalDataType::from_value(arg).unwrap(); + let dest_type = if from_type.scale() != size.scale() { + size.best_type() + } else { + from_type.data_kind().with_size(size) + }; + let value = decimal_to_decimal(arg, ctx, from_type, dest_type); + (value, dest_type) +} + trait DecimalConvert { fn convert(t: T, _scale: i32) -> U; } @@ -894,71 +990,59 @@ impl DecimalConvert for F64 { } } -fn decimal_to_float( - arg: &Value, - from_type: DataType, - ctx: &mut EvalContext, -) -> Value +fn decimal_to_float(arg: &Value, ctx: &mut EvalContext) -> Value where T: Number, T: DecimalConvert, T: DecimalConvert, { - let from_type = from_type.as_decimal().unwrap(); - - let result = if from_type.can_carried_by_128() { - let value = arg.try_downcast().unwrap(); - let scale = from_type.scale() as i32; - vectorize_1_arg::, NumberType>(|x, _ctx: &mut EvalContext| { - T::convert(x, scale) - })(value, ctx) - } else { - let value = arg.try_downcast().unwrap(); - let scale = from_type.scale() as i32; - vectorize_1_arg::, NumberType>(|x, _ctx: &mut EvalContext| { - T::convert(x, scale) - })(value, ctx) - }; - - result.upcast() + let (from_type, _) = DecimalDataType::from_value(arg).unwrap(); + match from_type { + DecimalDataType::Decimal64(size) => { + let value = arg.try_downcast().unwrap(); + let scale = size.scale() as i32; + vectorize_1_arg::>(|x, _| T::convert(x, scale))( + value, ctx, + ) + } + DecimalDataType::Decimal128(size) => { + let value = arg.try_downcast().unwrap(); + let scale = size.scale() as i32; + vectorize_1_arg::, NumberType>(|x, _| T::convert(x, scale))( + value, ctx, + ) + } + DecimalDataType::Decimal256(size) => { + let value = arg.try_downcast().unwrap(); + let scale = size.scale() as i32; + vectorize_1_arg::, NumberType>(|x, _| T::convert(x, scale))( + value, ctx, + ) + } + } + .upcast() } -fn decimal_to_int( - arg: &Value, - from_type: DataType, - ctx: &mut EvalContext, -) -> Value { - let from_type = from_type.as_decimal().unwrap(); - - let result = if from_type.can_carried_by_128() { - let value = arg.try_downcast().unwrap(); - vectorize_with_builder_1_arg::, NumberType>( - |x, builder: &mut Vec, ctx: &mut EvalContext| match x - .to_int(from_type.scale(), ctx.func_ctx.rounding_mode) - { - Some(x) => builder.push(x), - None => { - ctx.set_error(builder.len(), "decimal cast to int overflow"); - builder.push(T::default()) - } - }, - )(value, ctx) - } else { - let value = arg.try_downcast().unwrap(); - vectorize_with_builder_1_arg::, NumberType>( - |x, builder: &mut Vec, ctx: &mut EvalContext| match x - .to_int(from_type.scale(), ctx.func_ctx.rounding_mode) - { - Some(x) => builder.push(x), - None => { - ctx.set_error(builder.len(), "decimal cast to int overflow"); - builder.push(T::default()) - } - }, - )(value, ctx) - }; - - result.upcast() +fn decimal_to_int(arg: &Value, ctx: &mut EvalContext) -> Value { + with_decimal_mapped_type!( + |DECIMAL| match DecimalDataType::from_value(arg).unwrap().0 { + DecimalDataType::DECIMAL(size) => { + let value = arg.try_downcast().unwrap(); + vectorize_with_builder_1_arg::, NumberType>( + |x, builder: &mut Vec, ctx: &mut EvalContext| match x + .to_int(size.scale(), ctx.func_ctx.rounding_mode) + { + Some(x) => builder.push(x), + None => { + ctx.set_error(builder.len(), "decimal cast to int overflow"); + builder.push(T::default()) + } + }, + )(value, ctx) + } + } + ) + .upcast() } pub fn strict_decimal_data_type(mut data: DataBlock) -> Result { @@ -980,41 +1064,37 @@ pub fn strict_decimal_data_type(mut data: DataBlock) -> Result { - if size.can_carried_by_128() { - continue; - } + let size = from_type.size(); + match (size.can_carried_by_128(), from_type.data_kind()) { + (true, DecimalDataKind::Decimal128) | (false, DecimalDataKind::Decimal256) => continue, + (true, DecimalDataKind::Decimal64 | DecimalDataKind::Decimal256) => { if nullable { let nullable_value = entry.value.try_downcast::>().unwrap(); let value = nullable_value.value().unwrap(); let new_value = - decimal_to_decimal(&value, &mut ctx, from_type, Decimal256(size)); + decimal_to_decimal(&value, &mut ctx, from_type, Decimal128(size)); entry.value = new_value.wrap_nullable(Some(nullable_value.validity(ctx.num_rows))) } else { entry.value = - decimal_to_decimal(&entry.value, &mut ctx, from_type, Decimal256(size)) + decimal_to_decimal(&entry.value, &mut ctx, from_type, Decimal128(size)) } } - Decimal256(size) => { - if !size.can_carried_by_128() { - continue; - } + (false, DecimalDataKind::Decimal64 | DecimalDataKind::Decimal128) => { if nullable { let nullable_value = entry.value.try_downcast::>().unwrap(); let value = nullable_value.value().unwrap(); let new_value = - decimal_to_decimal(&value, &mut ctx, from_type, Decimal128(size)); + decimal_to_decimal(&value, &mut ctx, from_type, Decimal256(size)); entry.value = new_value.wrap_nullable(Some(nullable_value.validity(ctx.num_rows))) } else { entry.value = - decimal_to_decimal(&entry.value, &mut ctx, from_type, Decimal128(size)) + decimal_to_decimal(&entry.value, &mut ctx, from_type, Decimal256(size)) } } } diff --git a/src/query/functions/src/scalars/decimal/src/cast_from_jsonb.rs b/src/query/functions/src/scalars/decimal/src/cast_from_jsonb.rs index d5941de69f94e..cc0138745b450 100644 --- a/src/query/functions/src/scalars/decimal/src/cast_from_jsonb.rs +++ b/src/query/functions/src/scalars/decimal/src/cast_from_jsonb.rs @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::ops::Div; -use std::ops::Mul; - use databend_common_expression::serialize::read_decimal_with_size; use databend_common_expression::types::i256; use databend_common_expression::types::nullable::NullableColumnBuilder; @@ -33,7 +30,7 @@ use jsonb::Number as JsonbNumber; use jsonb::Value as JsonbValue; use num_traits::AsPrimitive; -use crate::cast::get_round_val; +use crate::decimal_scale_reduction; pub(super) fn variant_to_decimal( from: Value, @@ -42,10 +39,10 @@ pub(super) fn variant_to_decimal( only_cast_number: bool, ) -> Value>> where - T: Decimal + Mul + Div, + T: Decimal, { let size = dest_type.size(); - let multiplier = T::e(size.scale() as u32); + let multiplier = T::e(size.scale()); let multiplier_f64: f64 = (10_f64).powi(size.scale() as i32).as_(); let min = T::min_for_precision(size.precision()); let max = T::max_for_precision(size.precision()); @@ -103,7 +100,7 @@ fn cast_to_decimal( only_cast_number: bool, ) -> Result, String> where - T: Decimal + Mul + Div, + T: Decimal, { let value = jsonb::from_slice(val).map_err(|e| format!("Invalid jsonb value, {e}"))?; match value { @@ -116,23 +113,34 @@ where } JsonbNumber::Decimal128(d) => { let from_size = DecimalSize::new_unchecked(d.precision, d.scale); - let x = T::from_i128(d.value); - decimal_to_decimal::(x, min, max, from_size, dest_size, rounding_mode) - .map(|v| Some(v)) + match dest_type { + DecimalDataType::Decimal64(_) => { + let x = d.value; + let min = i128::min_for_precision(dest_size.precision()); + let max = i128::max_for_precision(dest_size.precision()); + decimal_to_decimal(x, min, max, from_size, dest_size, rounding_mode) + .map(|v| Some(T::from_i128(v))) + } + DecimalDataType::Decimal128(_) | DecimalDataType::Decimal256(_) => { + let x = T::from_i128(d.value); + decimal_to_decimal(x, min, max, from_size, dest_size, rounding_mode) + .map(|v| Some(v)) + } + } } JsonbNumber::Decimal256(d) => { let from_size = DecimalSize::new_unchecked(d.precision, d.scale); match dest_type { - DecimalDataType::Decimal128(_) => { + DecimalDataType::Decimal64(_) | DecimalDataType::Decimal128(_) => { let x = i256(d.value); let min = i256::min_for_precision(dest_size.precision()); let max = i256::max_for_precision(dest_size.precision()); - decimal_to_decimal::(x, min, max, from_size, dest_size, rounding_mode) + decimal_to_decimal(x, min, max, from_size, dest_size, rounding_mode) .map(|v| Some(T::from_i256(v))) } DecimalDataType::Decimal256(_) => { let x = T::from_i256(i256(d.value)); - decimal_to_decimal::(x, min, max, from_size, dest_size, rounding_mode) + decimal_to_decimal(x, min, max, from_size, dest_size, rounding_mode) .map(|v| Some(v)) } } @@ -146,7 +154,7 @@ where JsonbValue::Null => Ok(None), JsonbValue::Bool(b) => { let v = if b { - T::e(dest_size.scale() as u32) + T::e(dest_size.scale()) } else { T::zero() }; @@ -167,7 +175,7 @@ where fn integer_to_decimal(x: N, min: T, max: T, multiplier: T) -> Result where - T: Decimal + Mul, + T: Decimal, N: Number + AsPrimitive + std::fmt::Display, { if let Some(y) = T::from_i128(x.as_()).checked_mul(multiplier) { @@ -200,41 +208,32 @@ where Err(format!("Decimal overflow, value `{x}`")) } -fn decimal_to_decimal( +fn decimal_to_decimal( x: T, min: T, max: T, from_size: DecimalSize, dest_size: DecimalSize, rounding_mode: bool, -) -> Result -where - T: Decimal + Div, -{ +) -> Result { if from_size.scale() == dest_size.scale() && from_size.precision() <= dest_size.precision() { Ok(x) } else if from_size.scale() > dest_size.scale() { - let scale_diff = (from_size.scale() - dest_size.scale()) as u32; - let factor = T::e(scale_diff); - let source_factor = T::e(from_size.scale() as u32); - - let round_val = get_round_val::(x, scale_diff, rounding_mode); - let y = match (x.checked_div(factor), round_val) { - (Some(x), Some(round_val)) => x.checked_add(round_val), - (Some(x), None) => Some(x), - (None, _) => None, - }; - - match y { - Some(y) - if y <= max && y >= min && (y != T::zero() || x / source_factor == T::zero()) => - { - Ok(y) - } + let scale_diff = from_size.scale() - dest_size.scale(); + match decimal_scale_reduction( + x, + min, + max, + T::e(scale_diff), + from_size.scale(), + scale_diff, + rounding_mode, + ) { + Some(y) => Ok(y), _ => Err("Decimal overflow".to_string()), } } else { - let factor = T::e((dest_size.scale() - from_size.scale()) as u32); + let factor = T::e(dest_size.scale() - from_size.scale()); match x.checked_mul(factor) { Some(y) if y <= max && y >= min => Ok(y), _ => Err("Decimal overflow".to_string()), diff --git a/src/query/functions/src/scalars/decimal/src/comparison.rs b/src/query/functions/src/scalars/decimal/src/comparison.rs index 2162608b8e6cb..d0b77b9eb7c9e 100644 --- a/src/query/functions/src/scalars/decimal/src/comparison.rs +++ b/src/query/functions/src/scalars/decimal/src/comparison.rs @@ -13,13 +13,16 @@ // limitations under the License. use std::cmp::Ordering; +use std::hint::unlikely; use std::ops::*; use std::sync::Arc; +use databend_common_expression::types::compute_view::ComputeView; use databend_common_expression::types::decimal::*; use databend_common_expression::types::i256; use databend_common_expression::types::*; use databend_common_expression::vectorize_cmp_2_arg; +use databend_common_expression::with_decimal_mapped_type; use databend_common_expression::Domain; use databend_common_expression::EvalContext; use databend_common_expression::Function; @@ -34,10 +37,10 @@ use databend_common_expression::Value; use super::convert_to_decimal_domain; #[inline] -fn compare_multiplier(scale_a: u8, scale_b: u8) -> (u32, u32) { +fn compare_multiplier(scale_a: u8, scale_b: u8) -> (u8, u8) { ( - (scale_b - std::cmp::min(scale_a, scale_b)) as u32, - (scale_a - std::cmp::min(scale_a, scale_b)) as u32, + (scale_b - std::cmp::min(scale_a, scale_b)), + (scale_a - std::cmp::min(scale_a, scale_b)), ) } @@ -69,57 +72,36 @@ fn register_decimal_compare_op(registry: &mut FunctionRegistry) { }, eval: FunctionEval::Scalar { calc_domain: Box::new(|ctx, d| { - let (s1, s2) = ( - d[0].as_decimal().unwrap().decimal_size().scale(), - d[1].as_decimal().unwrap().decimal_size().scale(), - ); + let d1 = d[0].as_decimal().unwrap(); + let d2 = d[1].as_decimal().unwrap(); + + let (s1, s2) = (d1.decimal_size().scale(), d2.decimal_size().scale()); let (m1, m2) = compare_multiplier(s1, s2); - let new_domain = match (&d[0], &d[1]) { - ( - Domain::Decimal(DecimalDomain::Decimal128(d1, _)), - Domain::Decimal(DecimalDomain::Decimal128(d2, _)), - ) => { + let new_domain = match (d1, d2) { + (DecimalDomain::Decimal128(d1, _), DecimalDomain::Decimal128(d2, _)) => { let d1 = SimpleDomain { - min: d1.min.checked_mul(10_i128.pow(m1)).unwrap_or(i128::MIN), - max: d1.max.checked_mul(10_i128.pow(m1)).unwrap_or(i128::MAX), + min: d1.min.checked_mul(i128::e(m1)).unwrap_or(i128::DECIMAL_MIN), + max: d1.max.checked_mul(i128::e(m1)).unwrap_or(i128::DECIMAL_MAX), }; let d2 = SimpleDomain { - min: d2.min.checked_mul(10_i128.pow(m2)).unwrap_or(i128::MIN), - max: d2.max.checked_mul(10_i128.pow(m2)).unwrap_or(i128::MAX), + min: d2.min.checked_mul(i128::e(m2)).unwrap_or(i128::DECIMAL_MIN), + max: d2.max.checked_mul(i128::e(m2)).unwrap_or(i128::DECIMAL_MAX), }; Op::domain_op(&d1, &d2) } - ( - Domain::Decimal(DecimalDomain::Decimal256(d1, _)), - Domain::Decimal(DecimalDomain::Decimal256(d2, _)), - ) => { + (DecimalDomain::Decimal256(d1, _), DecimalDomain::Decimal256(d2, _)) => { let d1 = SimpleDomain { - min: d1 - .min - .checked_mul(i256::from(10).pow(m1)) - .unwrap_or(i256::MIN), - max: d1 - .max - .checked_mul(i256::from(10).pow(m1)) - .unwrap_or(i256::MAX), + min: d1.min.checked_mul(i256::e(m1)).unwrap_or(i256::DECIMAL_MIN), + max: d1.max.checked_mul(i256::e(m1)).unwrap_or(i256::DECIMAL_MAX), }; let d2 = SimpleDomain { - min: d2 - .min - .checked_mul(i256::from(10).pow(m2)) - .unwrap_or(i256::MIN), - max: d2 - .max - .checked_mul(i256::from(10).pow(m2)) - .unwrap_or(i256::MAX), + min: d2.min.checked_mul(i256::e(m2)).unwrap_or(i256::DECIMAL_MIN), + max: d2.max.checked_mul(i256::e(m2)).unwrap_or(i256::DECIMAL_MAX), }; Op::domain_op(&d1, &d2) } - ( - Domain::Decimal(DecimalDomain::Decimal128(_, _)), - Domain::Decimal(DecimalDomain::Decimal256(d2, _)), - ) => { + (DecimalDomain::Decimal128(_, _), DecimalDomain::Decimal256(d2, _)) => { let d1 = convert_to_decimal_domain( ctx, d[0].clone(), @@ -132,32 +114,17 @@ fn register_decimal_compare_op(registry: &mut FunctionRegistry) { let d1 = d1.as_decimal256().unwrap().0; let d1 = SimpleDomain { - min: d1 - .min - .checked_mul(i256::from(10).pow(m1)) - .unwrap_or(i256::MIN), - max: d1 - .max - .checked_mul(i256::from(10).pow(m1)) - .unwrap_or(i256::MAX), + min: d1.min.checked_mul(i256::e(m1)).unwrap_or(i256::DECIMAL_MIN), + max: d1.max.checked_mul(i256::e(m1)).unwrap_or(i256::DECIMAL_MAX), }; let d2 = SimpleDomain { - min: d2 - .min - .checked_mul(i256::from(10).pow(m2)) - .unwrap_or(i256::MIN), - max: d2 - .max - .checked_mul(i256::from(10).pow(m2)) - .unwrap_or(i256::MAX), + min: d2.min.checked_mul(i256::e(m2)).unwrap_or(i256::DECIMAL_MIN), + max: d2.max.checked_mul(i256::e(m2)).unwrap_or(i256::DECIMAL_MAX), }; Op::domain_op(&d1, &d2) } - ( - Domain::Decimal(DecimalDomain::Decimal256(d1, _)), - Domain::Decimal(DecimalDomain::Decimal128(_, _)), - ) => { + (DecimalDomain::Decimal256(d1, _), DecimalDomain::Decimal128(_, _)) => { let d2 = convert_to_decimal_domain( ctx, d[1].clone(), @@ -170,35 +137,21 @@ fn register_decimal_compare_op(registry: &mut FunctionRegistry) { let d2 = d2.as_decimal256().unwrap().0; let d1 = SimpleDomain { - min: d1 - .min - .checked_mul(i256::from(10).pow(m1)) - .unwrap_or(i256::MIN), - max: d1 - .max - .checked_mul(i256::from(10).pow(m1)) - .unwrap_or(i256::MAX), + min: d1.min.checked_mul(i256::e(m1)).unwrap_or(i256::DECIMAL_MIN), + max: d1.max.checked_mul(i256::e(m1)).unwrap_or(i256::DECIMAL_MAX), }; let d2 = SimpleDomain { - min: d2 - .min - .checked_mul(i256::from(10).pow(m2)) - .unwrap_or(i256::MIN), - max: d2 - .max - .checked_mul(i256::from(10).pow(m2)) - .unwrap_or(i256::MAX), + min: d2.min.checked_mul(i256::e(m2)).unwrap_or(i256::DECIMAL_MIN), + max: d2.max.checked_mul(i256::e(m2)).unwrap_or(i256::DECIMAL_MAX), }; Op::domain_op(&d1, &d2) } - _ => unreachable!(), + _ => unimplemented!(), }; new_domain.map(Domain::Boolean) }), - eval: Box::new(move |args, ctx| { - op_decimal::(&args[0], &args[1], &sig_types, ctx) - }), + eval: Box::new(move |args, ctx| op_decimal::(&args[0], &args[1], ctx)), }, }; if has_nullable { @@ -213,46 +166,50 @@ fn register_decimal_compare_op(registry: &mut FunctionRegistry) { fn op_decimal( a: &Value, b: &Value, - args_type: &[DataType], ctx: &mut EvalContext, ) -> Value { - use DecimalDataType::*; - - let (size_a, size_b) = ( - args_type[0].as_decimal().unwrap(), - args_type[1].as_decimal().unwrap(), - ); - let (m_a, m_b) = compare_multiplier(size_a.scale(), size_b.scale()); - let (a_type, _) = DecimalDataType::from_value(a).unwrap(); let (b_type, _) = DecimalDataType::from_value(b).unwrap(); + let size_calc = calc_size(&a_type.size(), &b_type.size()); - match (a_type, b_type) { - (Decimal128(_), Decimal128(_)) => { - let a = a.try_downcast::().unwrap(); - let b = b.try_downcast::().unwrap(); - let (f_a, f_b) = (10_i128.pow(m_a), 10_i128.pow(m_b)); - compare_decimal(a, b, |a, b, _| Op::compare(a, b, f_a, f_b), ctx) - } - (Decimal256(_), Decimal256(_)) => { - let a = a.try_downcast::().unwrap(); - let b = b.try_downcast::().unwrap(); - let (f_a, f_b) = (i256::from(10).pow(m_a), i256::from(10).pow(m_b)); - compare_decimal(a, b, |a, b, _| Op::compare(a, b, f_a, f_b), ctx) - } - (Decimal128(_), Decimal256(_)) => { - let a = a.try_downcast::().unwrap(); - let b = b.try_downcast::().unwrap(); - let (f_a, f_b) = (i256::from(10).pow(m_a), i256::from(10).pow(m_b)); - compare_decimal(a, b, |a, b, _| Op::compare(a, b, f_a, f_b), ctx) - } - (Decimal256(_), Decimal128(_)) => { - let a = a.try_downcast::().unwrap(); - let b = b.try_downcast::().unwrap(); - let (f_a, f_b) = (i256::from(10).pow(m_a), i256::from(10).pow(m_b)); - compare_decimal(a, b, |a, b, _| Op::compare(a, b, f_a, f_b), ctx) + with_decimal_mapped_type!(|T| match size_calc.best_type() { + DecimalDataType::T(_) => { + with_decimal_mapped_type!(|A| match a_type { + DecimalDataType::A(_) => { + with_decimal_mapped_type!(|B| match b_type { + DecimalDataType::B(_) => { + let a = a + .try_downcast::, _, _>>() + .unwrap(); + let b = b + .try_downcast::, _, _>>() + .unwrap(); + let (f_a, f_b) = ( + T::e(size_calc.scale() - a_type.scale()), + T::e(size_calc.scale() - b_type.scale()), + ); + compare_decimal(a, b, |a, b, _| Op::compare(a, b, f_a, f_b), ctx) + } + }) + } + }) } - } + }) +} + +fn calc_size(a: &DecimalSize, b: &DecimalSize) -> DecimalSize { + let scale = a.scale().max(b.scale()); + let precision = a.leading_digits().max(b.leading_digits()) + scale; + + // if the args both are Decimal128, we need to clamp the precision to 38 + let precision = + if a.precision() <= MAX_DECIMAL128_PRECISION && b.precision() <= MAX_DECIMAL128_PRECISION { + precision.min(MAX_DECIMAL128_PRECISION) + } else { + precision.min(MAX_DECIMAL256_PRECISION) + }; + + DecimalSize::new(precision, scale).unwrap() } fn compare_decimal( @@ -277,7 +234,7 @@ trait CmpOp { fn domain_op(a: &T, b: &T) -> FunctionDomain; fn compare(a: D, b: D, f_a: D, f_b: D) -> bool where D: Decimal + std::ops::Mul { - if a.signum() != b.signum() { + if unlikely(a.signum() != b.signum()) { return Self::is(a.cmp(&b)); } diff --git a/src/query/functions/src/scalars/decimal/src/hash.rs b/src/query/functions/src/scalars/decimal/src/hash.rs index 80c6bd83ca334..eea3f908e26ab 100644 --- a/src/query/functions/src/scalars/decimal/src/hash.rs +++ b/src/query/functions/src/scalars/decimal/src/hash.rs @@ -16,16 +16,10 @@ use std::hash::Hash; use std::hash::Hasher; use std::sync::Arc; +use databend_common_expression::types::decimal::*; use databend_common_expression::types::AccessType; use databend_common_expression::types::AnyType; use databend_common_expression::types::DataType; -use databend_common_expression::types::Decimal; -use databend_common_expression::types::Decimal128As256Type; -use databend_common_expression::types::Decimal128Type; -use databend_common_expression::types::Decimal256As128Type; -use databend_common_expression::types::Decimal256Type; -use databend_common_expression::types::DecimalDataType; -use databend_common_expression::types::DecimalSize; use databend_common_expression::types::Number; use databend_common_expression::types::NumberDataType; use databend_common_expression::types::NumberType; @@ -199,8 +193,12 @@ where let size = decimal_type.size(); if size.can_carried_by_128() { match decimal_type { + DecimalDataType::Decimal64(_) => { + let arg = arg.try_downcast::().unwrap(); + decimal_hash_typed::(arg, ctx, size.scale(), cast) + } DecimalDataType::Decimal128(_) => { - let arg: Value = arg.try_downcast().unwrap(); + let arg = arg.try_downcast::().unwrap(); decimal_hash_typed::(arg, ctx, size.scale(), cast) } DecimalDataType::Decimal256(_) => { @@ -210,6 +208,10 @@ where } } else { match decimal_type { + DecimalDataType::Decimal64(_) => { + let arg = arg.try_downcast::().unwrap(); + decimal_hash_typed::(arg, ctx, size.scale(), cast) + } DecimalDataType::Decimal128(_) => { let arg = arg.try_downcast::().unwrap(); decimal_hash_typed::(arg, ctx, size.scale(), cast) @@ -259,8 +261,13 @@ where let scale = size.scale(); if size.can_carried_by_128() { match decimal_type { + DecimalDataType::Decimal64(_) => { + let arg = arg.try_downcast::().unwrap(); + let seed: Value = seed.try_downcast().unwrap(); + decimal_hash_typed_with_seed::(arg, seed, ctx, scale, cast) + } DecimalDataType::Decimal128(_) => { - let arg: Value = arg.try_downcast().unwrap(); + let arg = arg.try_downcast::().unwrap(); let seed: Value = seed.try_downcast().unwrap(); decimal_hash_typed_with_seed::(arg, seed, ctx, scale, cast) } @@ -272,6 +279,11 @@ where } } else { match decimal_type { + DecimalDataType::Decimal64(_) => { + let arg = arg.try_downcast::().unwrap(); + let seed: Value = seed.try_downcast().unwrap(); + decimal_hash_typed_with_seed::(arg, seed, ctx, size.scale(), cast) + } DecimalDataType::Decimal128(_) => { let arg = arg.try_downcast::().unwrap(); let seed: Value = seed.try_downcast().unwrap(); diff --git a/src/query/functions/src/scalars/decimal/src/lib.rs b/src/query/functions/src/scalars/decimal/src/lib.rs index 54cba5391577b..4f71fe134f736 100644 --- a/src/query/functions/src/scalars/decimal/src/lib.rs +++ b/src/query/functions/src/scalars/decimal/src/lib.rs @@ -23,6 +23,7 @@ #![feature(try_blocks)] #![feature(downcast_unchecked)] #![feature(str_internals)] +#![feature(likely_unlikely)] mod arithmetic; mod cast; @@ -32,7 +33,7 @@ mod hash; mod math; mod uuid; -pub use arithmetic::register_decimal_arithmetic; +pub use arithmetic::*; pub use cast::*; pub use comparison::register_decimal_compare; pub use hash::*; diff --git a/src/query/functions/src/scalars/decimal/src/math.rs b/src/query/functions/src/scalars/decimal/src/math.rs index 39c8438d38c9e..6b65b203ee778 100644 --- a/src/query/functions/src/scalars/decimal/src/math.rs +++ b/src/query/functions/src/scalars/decimal/src/math.rs @@ -15,6 +15,8 @@ use std::ops::*; use std::sync::Arc; +use databend_common_expression::types::compute_view::Compute; +use databend_common_expression::types::compute_view::ComputeView; use databend_common_expression::types::decimal::*; use databend_common_expression::types::*; use databend_common_expression::vectorize_1_arg; @@ -40,7 +42,7 @@ pub fn register_decimal_math(registry: &mut FunctionRegistry) { return None; } - let from_size = from_type.as_decimal().unwrap(); + let from_size = *from_type.as_decimal().unwrap(); let scale = if params.is_empty() { debug_assert!(matches!(round_mode, RoundMode::Ceil | RoundMode::Floor)); @@ -49,12 +51,12 @@ pub fn register_decimal_math(registry: &mut FunctionRegistry) { params[0].get_i64()? }; - let decimal_size = DecimalSize::new_unchecked( + let return_size = DecimalSize::new( from_size.precision(), scale.clamp(0, from_size.scale() as _) as _, - ); + ) + .ok()?; - let dest_decimal_type = DecimalDataType::from_size(decimal_size).ok()?; let name = format!("{:?}", round_mode).to_lowercase(); let mut sig_args_type = args_type.to_owned(); @@ -63,16 +65,22 @@ pub fn register_decimal_math(registry: &mut FunctionRegistry) { signature: FunctionSignature { name, args_type: sig_args_type, - return_type: DataType::Decimal(dest_decimal_type.size()), + return_type: DataType::Decimal(return_size), }, eval: FunctionEval::Scalar { calc_domain: Box::new(move |_ctx, _d| FunctionDomain::Full), eval: Box::new(move |args, ctx| { + let dest_type = if !ctx.strict_eval && return_size.can_carried_by_64() { + DecimalDataType::Decimal64(return_size) + } else { + DecimalDataType::from(return_size) + }; + decimal_rounds( &args[0], ctx, - from_type.clone(), - dest_decimal_type, + dest_type, + from_size.scale() as _, scale as _, round_mode, ) @@ -146,32 +154,35 @@ enum RoundMode { Ceil, } -fn decimal_round_positive( +fn decimal_round_positive( value: Value>, source_scale: i64, target_scale: i64, ctx: &mut EvalContext, -) -> Value> +) -> Value> where T: Decimal + From + DivAssign + Div + Add + Sub, + U: Decimal, + C: Compute, CoreDecimal>, { - let power_of_ten = T::e((source_scale - target_scale) as u32); + let power_of_ten = T::e((source_scale - target_scale) as u8); let addition = power_of_ten / T::from(2); - vectorize_1_arg::, DecimalType>(|a, _| { - if a < T::zero() { + vectorize_1_arg::, DecimalType>(|a, _| { + let res = if a < T::zero() { (a - addition) / power_of_ten } else { (a + addition) / power_of_ten - } + }; + C::compute(&res) })(value, ctx) } -fn decimal_round_negative( +fn decimal_round_negative( value: Value>, source_scale: i64, target_scale: i64, ctx: &mut EvalContext, -) -> Value> +) -> Value> where T: Decimal + From @@ -180,41 +191,49 @@ where + Add + Sub + Mul, + U: Decimal, + C: Compute, CoreDecimal>, { - let divide_power_of_ten = T::e((source_scale - target_scale) as u32); + let divide_power_of_ten = T::e((source_scale - target_scale) as u8); let addition = divide_power_of_ten / T::from(2); - let multiply_power_of_ten = T::e((-target_scale) as u32); + let multiply_power_of_ten = T::e((-target_scale) as u8); - vectorize_1_arg::, DecimalType>(|a, _| { + vectorize_1_arg::, DecimalType>(|a, _| { let a = if a < T::zero() { a - addition } else { a + addition }; - a / divide_power_of_ten * multiply_power_of_ten + let res = a / divide_power_of_ten * multiply_power_of_ten; + C::compute(&res) })(value, ctx) } // if round mode is ceil, truncate should add one value -fn decimal_truncate_positive( +fn decimal_truncate_positive( value: Value>, source_scale: i64, target_scale: i64, ctx: &mut EvalContext, -) -> Value> +) -> Value> where T: Decimal + From + DivAssign + Div + Add + Sub, + U: Decimal, + C: Compute, CoreDecimal>, { - let power_of_ten = T::e((source_scale - target_scale) as u32); - vectorize_1_arg::, DecimalType>(|a, _| a / power_of_ten)(value, ctx) + let power_of_ten = T::e((source_scale - target_scale) as u8); + vectorize_1_arg::, DecimalType>(|a, _| { + let res = a / power_of_ten; + C::compute(&res) + })(value, ctx) } -fn decimal_truncate_negative( +fn decimal_truncate_negative( value: Value>, source_scale: i64, target_scale: i64, ctx: &mut EvalContext, -) -> Value> +) -> Value> where T: Decimal + From @@ -223,20 +242,23 @@ where + Add + Sub + Mul, + U: Decimal, + C: Compute, CoreDecimal>, { - let divide_power_of_ten = T::e((source_scale - target_scale) as u32); - let multiply_power_of_ten = T::e((-target_scale) as u32); + let divide_power_of_ten = T::e((source_scale - target_scale) as u8); + let multiply_power_of_ten = T::e((-target_scale) as u8); - vectorize_1_arg::, DecimalType>(|a, _| { - a / divide_power_of_ten * multiply_power_of_ten + vectorize_1_arg::, DecimalType>(|a, _| { + let res = a / divide_power_of_ten * multiply_power_of_ten; + C::compute(&res) })(value, ctx) } -fn decimal_floor( +fn decimal_floor( value: Value>, source_scale: i64, ctx: &mut EvalContext, -) -> Value> +) -> Value> where T: Decimal + From @@ -245,24 +267,27 @@ where + Add + Sub + Mul, + U: Decimal, + C: Compute, CoreDecimal>, { - let power_of_ten = T::e(source_scale as u32); + let power_of_ten = T::e(source_scale as u8); - vectorize_1_arg::, DecimalType>(|a, _| { - if a < T::zero() { + vectorize_1_arg::, DecimalType>(|a, _| { + let res = if a < T::zero() { // below 0 we ceil the number (e.g. -10.5 -> -11) ((a + T::one()) / power_of_ten) - T::one() } else { a / power_of_ten - } + }; + C::compute(&res) })(value, ctx) } -fn decimal_ceil( +fn decimal_ceil( value: Value>, source_scale: i64, ctx: &mut EvalContext, -) -> Value> +) -> Value> where T: Decimal + From @@ -271,70 +296,111 @@ where + Add + Sub + Mul, + U: Decimal, + C: Compute, CoreDecimal>, { - let power_of_ten = T::e(source_scale as u32); + let power_of_ten = T::e(source_scale as u8); - vectorize_1_arg::, DecimalType>(|a, _| { - if a <= T::zero() { + vectorize_1_arg::, DecimalType>(|a, _| { + let res = if a <= T::zero() { a / power_of_ten } else { ((a - T::one()) / power_of_ten) + T::one() - } + }; + C::compute(&res) })(value, ctx) } fn decimal_rounds( arg: &Value, ctx: &mut EvalContext, - from_type: DataType, dest_type: DecimalDataType, + source_scale: i64, target_scale: i64, mode: RoundMode, ) -> Value { - let size = from_type.as_decimal().unwrap(); - let source_scale = size.scale() as i64; + let (from_type, _) = DecimalDataType::from_value(arg).unwrap(); - if source_scale < target_scale { - return arg.clone().to_owned(); + if from_type.data_kind() == dest_type.data_kind() && source_scale < target_scale { + return arg.to_owned(); } - let zero_or_positive = target_scale >= 0; - - let (from_decimal_type, _) = DecimalDataType::from_value(arg).unwrap(); - with_decimal_mapped_type!(|TYPE| match from_decimal_type { - DecimalDataType::TYPE(_) => { - let value = arg.try_downcast::>().unwrap(); + with_decimal_mapped_type!(|IN| match from_type { + DecimalDataType::IN(_) => { + let arg = arg.try_downcast().unwrap(); + with_decimal_mapped_type!(|OUT| match dest_type { + DecimalDataType::OUT(size) => decimal_rounds_type::, _, _>( + arg, + ctx, + source_scale, + target_scale, + mode + ) + .upcast_decimal(size), + }) + } + }) +} - let result = match (zero_or_positive, mode) { - (true, RoundMode::Round) => { - decimal_round_positive(value, source_scale, target_scale, ctx) - } - (true, RoundMode::Truncate) => { - decimal_truncate_positive(value, source_scale, target_scale, ctx) - } - (false, RoundMode::Round) => { - decimal_round_negative(value, source_scale, target_scale, ctx) - } - (false, RoundMode::Truncate) => { - decimal_truncate_negative(value, source_scale, target_scale, ctx) - } - (_, RoundMode::Floor) => decimal_floor(value, source_scale, ctx), - (_, RoundMode::Ceil) => decimal_ceil(value, source_scale, ctx), - }; +fn decimal_rounds_type( + arg: Value>, + ctx: &mut EvalContext, + source_scale: i64, + target_scale: i64, + mode: RoundMode, +) -> Value> +where + T: Decimal + + From + + DivAssign + + Div + + Add + + Sub + + Mul, + U: Decimal, + C: Compute, CoreDecimal>, +{ + let zero_or_positive = target_scale >= 0; + match (mode, zero_or_positive) { + (RoundMode::Round, true) => { + decimal_round_positive::(arg, source_scale, target_scale, ctx) + } + (RoundMode::Round, false) => { + decimal_round_negative::(arg, source_scale, target_scale, ctx) + } - result.upcast_decimal(dest_type.size()) + (RoundMode::Truncate, true) => { + decimal_truncate_positive::(arg, source_scale, target_scale, ctx) } - }) + (RoundMode::Truncate, false) => { + decimal_truncate_negative::(arg, source_scale, target_scale, ctx) + } + + (RoundMode::Floor, _) => decimal_floor::(arg, source_scale, ctx), + (RoundMode::Ceil, _) => decimal_ceil::(arg, source_scale, ctx), + } } fn decimal_abs(arg: &Value, ctx: &mut EvalContext) -> Value { - let (data_type, _) = DecimalDataType::from_value(arg).unwrap(); - with_decimal_mapped_type!(|DECIMAL_TYPE| match data_type { - DecimalDataType::DECIMAL_TYPE(_) => { - type T = DecimalType; - let value = arg.try_downcast::().unwrap(); - let result = vectorize_1_arg::(|a, _| a.abs())(value, ctx); - result.upcast_decimal(data_type.size()) + let (from_type, _) = DecimalDataType::from_value(arg).unwrap(); + + let dest_type = if !ctx.strict_eval && from_type.size().can_carried_by_64() { + from_type + } else { + DecimalDataType::from(from_type.size()) + }; + + with_decimal_mapped_type!(|IN| match from_type { + DecimalDataType::IN(size) => { + with_decimal_mapped_type!(|OUT| match dest_type { + DecimalDataType::OUT(_) => { + let value = arg.try_downcast().unwrap(); + vectorize_1_arg::, _, _>, DecimalType>( + |a, _| a.abs(), + )(value, ctx) + .upcast_decimal(size) + } + }) } }) } diff --git a/src/query/functions/src/scalars/decimal/src/uuid.rs b/src/query/functions/src/scalars/decimal/src/uuid.rs index af176237f4d97..3045783ad7717 100644 --- a/src/query/functions/src/scalars/decimal/src/uuid.rs +++ b/src/query/functions/src/scalars/decimal/src/uuid.rs @@ -17,6 +17,7 @@ use databend_common_expression::types::string::StringColumnBuilder; use databend_common_expression::types::DataType; use databend_common_expression::types::Decimal128Type; use databend_common_expression::types::Decimal256As128Type; +use databend_common_expression::types::Decimal64As128Type; use databend_common_expression::types::DecimalDataType; use databend_common_expression::types::StringType; use databend_common_expression::vectorize_with_builder_1_arg; @@ -55,21 +56,23 @@ pub fn register_decimal_to_uuid(registry: &mut FunctionRegistry) { let arg = args[0].clone(); let (decimal_type, _) = DecimalDataType::from_value(&arg).unwrap(); match decimal_type { + DecimalDataType::Decimal64(_) => { + type T = Decimal64As128Type; + let arg = arg.try_downcast::().unwrap(); + vectorize_with_builder_1_arg::(to_uuid)(arg, ctx) + } DecimalDataType::Decimal128(_) => { - let arg = arg.try_downcast::().unwrap(); - vectorize_with_builder_1_arg::(to_uuid)( - arg, ctx, - ) - .upcast() + type T = Decimal128Type; + let arg = arg.try_downcast::().unwrap(); + vectorize_with_builder_1_arg::(to_uuid)(arg, ctx) } DecimalDataType::Decimal256(_) => { - let arg = arg.try_downcast::().unwrap(); - vectorize_with_builder_1_arg::( - to_uuid, - )(arg, ctx) - .upcast() + type T = Decimal256As128Type; + let arg = arg.try_downcast::().unwrap(); + vectorize_with_builder_1_arg::(to_uuid)(arg, ctx) } } + .upcast() }), }, }) diff --git a/src/query/functions/src/scalars/hilbert.rs b/src/query/functions/src/scalars/hilbert.rs index f9f1942e56d2b..19a9f5638cd83 100644 --- a/src/query/functions/src/scalars/hilbert.rs +++ b/src/query/functions/src/scalars/hilbert.rs @@ -15,7 +15,6 @@ use std::sync::Arc; use databend_common_expression::hilbert_index; -use databend_common_expression::types::AccessType; use databend_common_expression::types::ArrayType; use databend_common_expression::types::BinaryType; use databend_common_expression::types::DataType; diff --git a/src/query/functions/src/scalars/mod.rs b/src/query/functions/src/scalars/mod.rs index 9eaf091eb5eac..78902a6beb91f 100644 --- a/src/query/functions/src/scalars/mod.rs +++ b/src/query/functions/src/scalars/mod.rs @@ -55,6 +55,7 @@ pub use string::ALL_STRING_FUNC_NAMES; pub fn register(registry: &mut FunctionRegistry) { variant::register(registry); + databend_functions_scalar_decimal::register_decimal_minus(registry); arithmetic::register(registry); // register basic arithmetic operation (+ - * / %) databend_functions_scalar_decimal::register_decimal_arithmetic(registry); diff --git a/src/query/functions/src/srfs/variant.rs b/src/query/functions/src/srfs/variant.rs index 75db5f8a6cb36..aa66e465f1c63 100644 --- a/src/query/functions/src/srfs/variant.rs +++ b/src/query/functions/src/srfs/variant.rs @@ -20,7 +20,6 @@ use databend_common_exception::Result; use databend_common_expression::types::binary::BinaryColumnBuilder; use databend_common_expression::types::nullable::NullableColumnBuilder; use databend_common_expression::types::string::StringColumnBuilder; -use databend_common_expression::types::AccessType; use databend_common_expression::types::AnyType; use databend_common_expression::types::Bitmap; use databend_common_expression::types::DataType; @@ -28,6 +27,7 @@ use databend_common_expression::types::NullableType; use databend_common_expression::types::NumberDataType; use databend_common_expression::types::StringType; use databend_common_expression::types::UInt64Type; +use databend_common_expression::types::ValueType; use databend_common_expression::types::VariantType; use databend_common_expression::Column; use databend_common_expression::FromData; diff --git a/src/query/functions/tests/it/aggregates/agg.rs b/src/query/functions/tests/it/aggregates/agg.rs index 4f2f877b5887a..6a136d3553fb0 100644 --- a/src/query/functions/tests/it/aggregates/agg.rs +++ b/src/query/functions/tests/it/aggregates/agg.rs @@ -205,7 +205,7 @@ fn get_example() -> Vec<(&'static str, Column)> { "dec", Decimal128Type::from_opt_data_with_size( vec![Some(110), Some(220), None, Some(330)], - DecimalSize::new_unchecked(15, 2), + Some(DecimalSize::new_unchecked(15, 2)), ), ), ] diff --git a/src/query/functions/tests/it/scalars/arithmetic.rs b/src/query/functions/tests/it/scalars/arithmetic.rs index 13bda0631492e..7301eeade535c 100644 --- a/src/query/functions/tests/it/scalars/arithmetic.rs +++ b/src/query/functions/tests/it/scalars/arithmetic.rs @@ -18,11 +18,14 @@ use databend_common_expression::types::decimal::DecimalColumn; use databend_common_expression::types::decimal::DecimalSize; use databend_common_expression::types::i256; use databend_common_expression::types::number::*; +use databend_common_expression::types::Decimal64Type; use databend_common_expression::Column; use databend_common_expression::FromData; use goldenfile::Mint; use super::run_ast; +use super::run_ast_with_context; +use super::TestContext; #[test] fn test_arithmetic() { @@ -267,3 +270,54 @@ fn test_bitwise_shift_right(file: &mut impl Write, columns: &[(&str, Column)]) { run_ast(file, "a2 >> 2", columns); run_ast(file, "c >> 2", columns); } + +#[test] +fn test_decimal() { + let mut mint = Mint::new("tests/it/scalars/testdata"); + let file = &mut mint.new_goldenfile("arithmetic_decimal.txt").unwrap(); + + let columns = [ + ( + "l_extendedprice", + Decimal64Type::from_data_with_size( + [ + 7029081, 3988040, 2696083, 8576832, 3179020, 1941184, 6911822, 4874825, + 4207270, 4425444, + ], + Some(DecimalSize::new_unchecked(15, 2)), + ), + ), + ( + "l_discount", + Decimal64Type::from_data_with_size( + [8, 8, 0, 9, 7, 7, 7, 9, 9, 2], + Some(DecimalSize::new_unchecked(15, 2)), + ), + ), + ( + "ps_supplycost", + Decimal64Type::from_data_with_size( + [ + 32776, 34561, 52627, 45035, 65850, 11521, 34965, 79552, 42880, 48615, + ], + Some(DecimalSize::new_unchecked(15, 2)), + ), + ), + ( + "l_quantity", + Decimal64Type::from_data_with_size( + [4300, 4000, 2300, 4800, 2000, 1600, 4600, 2500, 3700, 3600], + Some(DecimalSize::new_unchecked(15, 2)), + ), + ), + ]; + + run_ast_with_context( + file, + "l_extendedprice + (1 - l_discount) - l_quantity", + TestContext { + columns: &columns, + ..Default::default() + }, + ) +} diff --git a/src/query/functions/tests/it/scalars/cast.rs b/src/query/functions/tests/it/scalars/cast.rs index 9e1ad7c939d65..eedd9e86a3f6f 100644 --- a/src/query/functions/tests/it/scalars/cast.rs +++ b/src/query/functions/tests/it/scalars/cast.rs @@ -17,11 +17,14 @@ use std::io::Write; use databend_common_expression::types::*; use databend_common_expression::Column; use databend_common_expression::FromData; +use databend_common_expression::FunctionContext; use goldenfile::Mint; use itertools::Itertools; use roaring::RoaringTreemap; use super::run_ast; +use super::run_ast_with_context; +use super::TestContext; #[test] fn test_cast() { @@ -754,6 +757,358 @@ fn test_cast_between_binary_and_string(file: &mut impl Write, is_try: bool) { ); } +#[test] +fn test_decimal_to_decimal() { + let mut mint = Mint::new("tests/it/scalars/testdata"); + let file = &mut mint.new_goldenfile("decimal_to_decimal_cast.txt").unwrap(); + + for is_try in [false, true] { + test_cast_decimal_basic(file, is_try); + test_cast_decimal_scale_reduction(file, is_try, true); + test_cast_decimal_scale_reduction(file, is_try, false); + test_cast_decimal_precision_reduction(file, is_try); + test_cast_decimal_cross_type(file, is_try); + test_cast_decimal_with_columns(file, is_try); + } +} + +fn test_cast_decimal_basic(file: &mut impl Write, is_try: bool) { + let prefix = if is_try { "TRY_" } else { "" }; + + // Test basic decimal to decimal casting with same precision/scale + run_ast( + file, + format!("{prefix}CAST(123.45::DECIMAL(5,2) AS DECIMAL(5,2))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(0.00::DECIMAL(3,2) AS DECIMAL(3,2))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(-999.99::DECIMAL(5,2) AS DECIMAL(5,2))"), + &[], + ); + + // Test expanding precision (same scale) + run_ast( + file, + format!("{prefix}CAST(123.45::DECIMAL(5,2) AS DECIMAL(10,2))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(-123.45::DECIMAL(5,2) AS DECIMAL(15,2))"), + &[], + ); + + // Test expanding scale (same precision) + run_ast( + file, + format!("{prefix}CAST(123.45::DECIMAL(5,2) AS DECIMAL(5,4))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(123::DECIMAL(3,0) AS DECIMAL(3,2))"), + &[], + ); + + // Test expanding both precision and scale + run_ast( + file, + format!("{prefix}CAST(123.45::DECIMAL(5,2) AS DECIMAL(10,4))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(1.2::DECIMAL(2,1) AS DECIMAL(20,10))"), + &[], + ); + + // Test edge cases with zero + run_ast( + file, + format!("{prefix}CAST(0::DECIMAL(1,0) AS DECIMAL(10,5))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(0.00000::DECIMAL(6,5) AS DECIMAL(2,1))"), + &[], + ); +} + +fn test_cast_decimal_scale_reduction(file: &mut impl Write, is_try: bool, rounding_mode: bool) { + let prefix = if is_try { "TRY_" } else { "" }; + let func_ctx = FunctionContext { + rounding_mode, + ..FunctionContext::default() + }; + let test_ctx = TestContext { + func_ctx: func_ctx.clone(), + ..TestContext::default() + }; + + // Test shrinking scale (same precision) - precision loss with rounding + run_ast_with_context( + file, + format!("{prefix}CAST(123.456::DECIMAL(6,3) AS DECIMAL(6,1))"), + test_ctx.clone(), + ); + run_ast_with_context( + file, + format!("{prefix}CAST(123.999::DECIMAL(6,3) AS DECIMAL(6,2))"), + test_ctx.clone(), + ); + run_ast_with_context( + file, + format!("{prefix}CAST(999.995::DECIMAL(6,3) AS DECIMAL(6,1))"), + test_ctx.clone(), + ); + + // Test scale reduction with different rounding scenarios + run_ast_with_context( + file, + format!("{prefix}CAST(12.345::DECIMAL(5,3) AS DECIMAL(5,0))"), + test_ctx.clone(), + ); + run_ast_with_context( + file, + format!("{prefix}CAST(12.567::DECIMAL(5,3) AS DECIMAL(5,1))"), + test_ctx.clone(), + ); + run_ast_with_context( + file, + format!("{prefix}CAST(-12.345::DECIMAL(6,3) AS DECIMAL(6,1))"), + test_ctx.clone(), + ); + run_ast_with_context( + file, + format!("{prefix}CAST(-12.567::DECIMAL(6,3) AS DECIMAL(6,2))"), + test_ctx.clone(), + ); + + // Test scale reduction with edge cases + run_ast_with_context( + file, + format!("{prefix}CAST(0.999::DECIMAL(4,3) AS DECIMAL(4,0))"), + test_ctx.clone(), + ); + run_ast_with_context( + file, + format!("{prefix}CAST(0.001::DECIMAL(4,3) AS DECIMAL(4,1))"), + test_ctx.clone(), + ); + + // Test scale reduction with column data + let test_ctx = TestContext { + columns: &[( + "c", + Decimal128Type::from_data_with_size( + [12345i128, 67890, -11111, 99999, 0, -99999, 123456], + Some(DecimalSize::new_unchecked(8, 3)), + ), + )], + func_ctx, + ..TestContext::default() + }; + + run_ast_with_context( + file, + format!("{prefix}CAST(c AS DECIMAL(8,0))"), + test_ctx.clone(), + ); + run_ast_with_context( + file, + format!("{prefix}CAST(c AS DECIMAL(8,1))"), + test_ctx.clone(), + ); + run_ast_with_context( + file, + format!("{prefix}CAST(c AS DECIMAL(8,2))"), + test_ctx.clone(), + ); +} + +fn test_cast_decimal_precision_reduction(file: &mut impl Write, is_try: bool) { + let prefix = if is_try { "TRY_" } else { "" }; + + // Test shrinking precision (same scale) - potential overflow + run_ast( + file, + format!("{prefix}CAST(12345.67::DECIMAL(7,2) AS DECIMAL(5,2))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(999.99::DECIMAL(5,2) AS DECIMAL(4,2))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(99.9::DECIMAL(3,1) AS DECIMAL(2,1))"), + &[], + ); + + // Test negative numbers with precision reduction + run_ast( + file, + format!("{prefix}CAST(-999.999::DECIMAL(6,3) AS DECIMAL(4,1))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(-123.45::DECIMAL(5,2) AS DECIMAL(4,2))"), + &[], + ); + + // Test edge cases - maximum values for target precision + run_ast( + file, + format!("{prefix}CAST(99.99::DECIMAL(4,2) AS DECIMAL(3,2))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(9.99::DECIMAL(3,2) AS DECIMAL(2,2))"), + &[], + ); +} + +fn test_cast_decimal_cross_type(file: &mut impl Write, is_try: bool) { + let prefix = if is_try { "TRY_" } else { "" }; + + // Test cross-type casting (different decimal storage types) + run_ast( + file, + format!("{prefix}CAST(123.45::DECIMAL(5,2) AS DECIMAL(38,10))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(123456789.123456789::DECIMAL(18,9) AS DECIMAL(38,20))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(12345678901234567890.123456789::DECIMAL(38,9) AS DECIMAL(18,4))"), + &[], + ); + + // Test maximum values for different precisions + run_ast( + file, + format!("{prefix}CAST(99.99::DECIMAL(4,2) AS DECIMAL(6,2))"), + &[], + ); + run_ast( + file, + format!("{prefix}CAST(999999.999::DECIMAL(9,3) AS DECIMAL(15,6))"), + &[], + ); +} + +fn test_cast_decimal_with_columns(file: &mut impl Write, is_try: bool) { + let prefix = if is_try { "TRY_" } else { "" }; + + // Test with column data - similar to comparison.rs test_decimal pattern + let decimal_128_data = vec![0i128, 1, -1, 123456789, -987654321, 999999]; + let decimal_256_data = vec![ + i256::zero(), + 2.into(), + (-2).into(), + 123456780.into(), + (-987654320).into(), + 1000000.into(), + ]; + + let decimal_columns = &[ + ( + "a", + Decimal128Type::from_data_with_size( + &decimal_128_data, + Some(DecimalSize::new_unchecked(10, 2)), + ), + ), + ( + "b", + Decimal256Type::from_data_with_size( + &decimal_256_data, + Some(DecimalSize::new_unchecked(15, 3)), + ), + ), + ]; + + // Test casting between different decimal column types + run_ast( + file, + format!("{prefix}CAST(a AS DECIMAL(15,3))"), + decimal_columns, + ); + run_ast( + file, + format!("{prefix}CAST(a AS DECIMAL(20,5))"), + decimal_columns, + ); + run_ast( + file, + format!("{prefix}CAST(b AS DECIMAL(10,2))"), + decimal_columns, + ); + run_ast( + file, + format!("{prefix}CAST(b AS DECIMAL(38,10))"), + decimal_columns, + ); + + // Test casting with potential overflow/underflow + run_ast( + file, + format!("{prefix}CAST(a AS DECIMAL(5,1))"), + decimal_columns, + ); + run_ast( + file, + format!("{prefix}CAST(b AS DECIMAL(8,2))"), + decimal_columns, + ); + + // Test edge cases with very large numbers + let large_decimal_data = vec![ + i256::from(999999999999999999i128), + i256::from(-999999999999999999i128), + i256::zero(), + i256::from(123456789012345i128), + i256::from(-123456789012345i128), + ]; + let large_columns = &[( + "d", + Decimal256Type::from_data_with_size( + &large_decimal_data, + Some(DecimalSize::new_unchecked(38, 10)), + ), + )]; + + run_ast( + file, + format!("{prefix}CAST(d AS DECIMAL(20,5))"), + large_columns, + ); + run_ast( + file, + format!("{prefix}CAST(d AS DECIMAL(38,15))"), + large_columns, + ); + run_ast( + file, + format!("{prefix}CAST(d AS DECIMAL(15,2))"), + large_columns, + ); +} + fn gen_bitmap_data() -> Column { // construct bitmap column with 4 row: // 0..5, 1..6, 2..7, 3..8 diff --git a/src/query/functions/tests/it/scalars/comparison.rs b/src/query/functions/tests/it/scalars/comparison.rs index 3be6b8ec57eaa..b2343ec996fcb 100644 --- a/src/query/functions/tests/it/scalars/comparison.rs +++ b/src/query/functions/tests/it/scalars/comparison.rs @@ -484,15 +484,15 @@ fn test_decimal(file: &mut impl Write) { let decimals = &[ ( "a", - Decimal128Type::from_data_with_size(&data_a, DecimalSize::new_unchecked(10, 2)), + Decimal128Type::from_data_with_size(&data_a, Some(DecimalSize::new_unchecked(10, 2))), ), ( "b", - Decimal256Type::from_data_with_size(&data_b, DecimalSize::new_unchecked(10, 2)), + Decimal256Type::from_data_with_size(&data_b, Some(DecimalSize::new_unchecked(10, 2))), ), ( "c", - Decimal256Type::from_data_with_size(&data_b, DecimalSize::new_unchecked(10, 3)), + Decimal256Type::from_data_with_size(&data_b, Some(DecimalSize::new_unchecked(10, 3))), ), ]; run_ast(file, "a > b", decimals); diff --git a/src/query/functions/tests/it/scalars/hash.rs b/src/query/functions/tests/it/scalars/hash.rs index fab9145666121..3480d82045e9a 100644 --- a/src/query/functions/tests/it/scalars/hash.rs +++ b/src/query/functions/tests/it/scalars/hash.rs @@ -100,17 +100,17 @@ fn test_city64withseed(file: &mut impl Write) { let size = DecimalSize::new(10, 0).unwrap(); run_ast(file, "city64withseed(a,5)", &[( "a", - Decimal128Type::from_data_with_size([0, 1, 2], size), + Decimal128Type::from_data_with_size([0, 1, 2], Some(size)), )]); run_ast(file, "city64withseed(a,5)", &[( "a", - Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], size), + Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], Some(size)), )]); run_ast(file, "city64withseed(a,5)", &[( "a", Decimal256Type::from_data_with_size( [i256::from(0), i256::from(20)], - DecimalSize::new(40, 0).unwrap(), + Some(DecimalSize::new(40, 0).unwrap()), ), )]); } @@ -152,17 +152,17 @@ fn test_xxhash64(file: &mut impl Write) { let size = DecimalSize::new(10, 0).unwrap(); run_ast(file, "xxhash64(a)", &[( "a", - Decimal128Type::from_data_with_size([0, 1, 2], size), + Decimal128Type::from_data_with_size([0, 1, 2], Some(size)), )]); run_ast(file, "xxhash64(a)", &[( "a", - Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], size), + Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], Some(size)), )]); run_ast(file, "xxhash64(a)", &[( "a", Decimal256Type::from_data_with_size( [i256::from(0), i256::from(20)], - DecimalSize::new(40, 0).unwrap(), + Some(DecimalSize::new(40, 0).unwrap()), ), )]); } @@ -187,17 +187,17 @@ fn test_xxhash32(file: &mut impl Write) { let size = DecimalSize::new(10, 0).unwrap(); run_ast(file, "xxhash32(a)", &[( "a", - Decimal128Type::from_data_with_size([0, 1, 2], size), + Decimal128Type::from_data_with_size([0, 1, 2], Some(size)), )]); run_ast(file, "xxhash32(a)", &[( "a", - Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], size), + Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], Some(size)), )]); run_ast(file, "xxhash32(a)", &[( "a", Decimal256Type::from_data_with_size( [i256::from(0), i256::from(20)], - DecimalSize::new(40, 0).unwrap(), + Some(DecimalSize::new(40, 0).unwrap()), ), )]); } diff --git a/src/query/functions/tests/it/scalars/mod.rs b/src/query/functions/tests/it/scalars/mod.rs index 5f0dd1baeb7a1..6fa21da636800 100644 --- a/src/query/functions/tests/it/scalars/mod.rs +++ b/src/query/functions/tests/it/scalars/mod.rs @@ -23,6 +23,7 @@ use databend_common_expression::BlockEntry; use databend_common_expression::Column; use databend_common_expression::ConstantFolder; use databend_common_expression::DataBlock; +use databend_common_expression::Domain; use databend_common_expression::Evaluator; use databend_common_expression::FunctionContext; use databend_common_expression::FunctionFactory; @@ -61,12 +62,60 @@ mod vector; pub use databend_common_functions::test_utils as parser; +#[derive(Clone)] +pub struct TestContext<'a> { + pub columns: &'a [(&'a str, Column)], + pub input_domains: Option<&'a [(&'a str, Domain)]>, + pub func_ctx: FunctionContext, + pub strict_eval: bool, +} + +impl Default for TestContext<'_> { + fn default() -> Self { + Self { + columns: &[], + input_domains: None, + func_ctx: FunctionContext::default(), + strict_eval: true, + } + } +} + +impl<'a> TestContext<'a> { + pub fn input_domains(&mut self) -> HashMap { + self.columns + .iter() + .map(|(name, col)| { + self.input_domains + .and_then(|domains| { + domains + .iter() + .find(|(n, _)| n == name) + .map(|(_, domain)| domain.clone()) + }) + .unwrap_or_else(|| col.domain()) + }) + .enumerate() + .collect() + } +} + pub fn run_ast(file: &mut impl Write, text: impl AsRef, columns: &[(&str, Column)]) { + run_ast_with_context(file, text, TestContext { + columns, + func_ctx: FunctionContext::default(), + input_domains: None, + strict_eval: true, + }) +} + +pub fn run_ast_with_context(file: &mut impl Write, text: impl AsRef, mut ctx: TestContext) { let text = text.as_ref(); + let result: Result<_> = try { let raw_expr = parser::parse_raw_expr( text, - &columns + &ctx.columns .iter() .map(|(name, c)| (*name, c.data_type())) .collect::>(), @@ -75,39 +124,42 @@ pub fn run_ast(file: &mut impl Write, text: impl AsRef, columns: &[(&str, C let expr = type_check::check(&raw_expr, &BUILTIN_FUNCTIONS)?; let expr = type_check::rewrite_function_to_cast(expr); - let input_domains = columns - .iter() - .map(|(_, col)| col.domain()) - .enumerate() - .collect::>(); + let input_domains = ctx.input_domains(); let (optimized_expr, output_domain) = ConstantFolder::fold_with_domain( &expr, &input_domains, - &FunctionContext::default(), + &ctx.func_ctx, &BUILTIN_FUNCTIONS, ); let remote_expr = optimized_expr.as_remote_expr(); let optimized_expr = remote_expr.as_expr(&BUILTIN_FUNCTIONS); - let num_rows = columns.iter().map(|col| col.1.len()).max().unwrap_or(1); + let num_rows = ctx.columns.iter().map(|col| col.1.len()).max().unwrap_or(1); let block = DataBlock::new( - columns + ctx.columns .iter() .map(|(_, col)| BlockEntry::new(col.data_type(), Value::Column(col.clone()))) .collect::>(), num_rows, ); - columns.iter().for_each(|(_, col)| { - test_arrow_conversion_input(col); + ctx.columns.iter().for_each(|(_, col)| { + test_arrow_conversion(col, false); }); - let func_ctx = FunctionContext::default(); - let evaluator = Evaluator::new(&block, &func_ctx, &BUILTIN_FUNCTIONS); - let result = evaluator.run(&expr); - let optimized_result = evaluator.run(&optimized_expr); + let evaluator = Evaluator::new(&block, &ctx.func_ctx, &BUILTIN_FUNCTIONS); + let result = if ctx.strict_eval { + evaluator.run(&expr) + } else { + evaluator.run_fast(&expr) + }; + let optimized_result = if ctx.strict_eval { + evaluator.run(&optimized_expr) + } else { + evaluator.run_fast(&expr) + }; match &result { Ok(result) => assert!( result.semantically_eq(&optimized_result.clone().unwrap()), @@ -145,6 +197,9 @@ pub fn run_ast(file: &mut impl Write, text: impl AsRef, columns: &[(&str, C if optimized_expr != expr { writeln!(file, "optimized expr : {optimized_expr}").unwrap(); } + if ctx.func_ctx != FunctionContext::default() { + writeln!(file, "func ctx : (modified)").unwrap(); + } match result { Value::Scalar(output_scalar) => { @@ -153,7 +208,7 @@ pub fn run_ast(file: &mut impl Write, text: impl AsRef, columns: &[(&str, C writeln!(file, "output : {}", output_scalar.as_ref()).unwrap(); } Value::Column(output_col) => { - test_arrow_conversion_output(&output_col); + test_arrow_conversion(&output_col, ctx.strict_eval); // Only display the used input columns let used_columns = raw_expr @@ -169,7 +224,7 @@ pub fn run_ast(file: &mut impl Write, text: impl AsRef, columns: &[(&str, C .collect::>(); let columns = used_columns .into_iter() - .map(|i| columns[i].clone()) + .map(|i| ctx.columns[i].clone()) .collect::>(); let mut table = Table::new(); @@ -224,18 +279,22 @@ pub fn run_ast(file: &mut impl Write, text: impl AsRef, columns: &[(&str, C } } -fn test_arrow_conversion_input(col: &Column) { +fn test_arrow_conversion(col: &Column, strict: bool) { let data_type = col.data_type(); - let col = match col { - Column::Decimal(decimal) => Column::Decimal(decimal.clone().strict_decimal_data_type()), - col @ Column::Nullable(nullable) => match &nullable.column { - Column::Decimal(decimal) => Column::Nullable(Box::new(NullableColumn { - column: Column::Decimal(decimal.clone().strict_decimal_data_type()), - validity: nullable.validity.clone(), - })), - _ => col.clone(), - }, - col => col.clone(), + let col = if !strict { + match col { + Column::Decimal(decimal) => Column::Decimal(decimal.clone().strict_decimal_data_type()), + col @ Column::Nullable(nullable) => match &nullable.column { + Column::Decimal(decimal) => Column::Nullable(Box::new(NullableColumn { + column: Column::Decimal(decimal.clone().strict_decimal_data_type()), + validity: nullable.validity.clone(), + })), + _ => col.clone(), + }, + col => col.clone(), + } + } else { + col.clone() }; let arrow_col = col.clone().into_arrow_rs(); @@ -243,12 +302,6 @@ fn test_arrow_conversion_input(col: &Column) { assert_eq!(col, new_col, "arrow conversion went wrong"); } -fn test_arrow_conversion_output(col: &Column) { - let arrow_col = col.clone().into_arrow_rs(); - let new_col = Column::from_arrow_rs(arrow_col, &col.data_type()).unwrap(); - assert_eq!(col, &new_col, "arrow conversion went wrong"); -} - #[test] fn list_all_builtin_functions() { let mut mint = Mint::new("tests/it/scalars/testdata"); diff --git a/src/query/functions/tests/it/scalars/string.rs b/src/query/functions/tests/it/scalars/string.rs index 1d493e5c670ff..99f9c7b10001b 100644 --- a/src/query/functions/tests/it/scalars/string.rs +++ b/src/query/functions/tests/it/scalars/string.rs @@ -774,26 +774,26 @@ fn test_to_uuid(file: &mut impl Write) { let size = DecimalSize::new(10, 0).unwrap(); run_ast(file, "to_uuid(a)", &[( "a", - Decimal128Type::from_data_with_size([0, 1, 2], size), + Decimal128Type::from_data_with_size([0, 1, 2], Some(size)), )]); run_ast(file, "to_uuid(a)", &[( "a", - Decimal128Type::from_data_with_size([0, 1, 2], size).wrap_nullable(None), + Decimal128Type::from_data_with_size([0, 1, 2], Some(size)).wrap_nullable(None), )]); run_ast(file, "to_uuid(a)", &[( "a", - Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], size), + Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], Some(size)), )]); run_ast(file, "to_uuid(a)", &[( "a", - Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], size) + Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], Some(size)) .wrap_nullable(None), )]); run_ast(file, "to_uuid(a)", &[( "a", Decimal256Type::from_data_with_size( [i256::from(0), i256::from(20)], - DecimalSize::new(40, 0).unwrap(), + Some(DecimalSize::new(40, 0).unwrap()), ), )]); } diff --git a/src/query/functions/tests/it/scalars/testdata/arithmetic.txt b/src/query/functions/tests/it/scalars/testdata/arithmetic.txt index b7f9fc2df3477..21c59e39967b0 100644 --- a/src/query/functions/tests/it/scalars/testdata/arithmetic.txt +++ b/src/query/functions/tests/it/scalars/testdata/arithmetic.txt @@ -1248,7 +1248,7 @@ evaluation: +--------+------------------+----------------+---------------------+ | | d2 | f | Output | +--------+------------------+----------------+---------------------+ -| Type | UInt8 NULL | Decimal(76, 2) | Decimal(39, 6) NULL | +| Type | UInt8 NULL | Decimal(76, 2) | Decimal(11, 6) NULL | | Domain | {1..=3} ∪ {NULL} | {0.50..=12.34} | Unknown | | Row 0 | 1 | 0.50 | 2.000000 | | Row 1 | NULL | 0.92 | NULL | @@ -1260,7 +1260,7 @@ evaluation (internal): +--------+-----------------------------------------------------------------------------------------------+ | d2 | NullableColumn { column: UInt8([1, 0, 3]), validity: [0b_____101] } | | f | Decimal256([0.50, 0.92, 12.34]) | -| Output | NullableColumn { column: Decimal256([2.000000, 0.000000, 0.243112]), validity: [0b_____101] } | +| Output | NullableColumn { column: Decimal128([2.000000, 0.000000, 0.243112]), validity: [0b_____101] } | +--------+-----------------------------------------------------------------------------------------------+ @@ -1271,7 +1271,7 @@ evaluation: +--------+----------------+----------------+----------------+ | | e | f | Output | +--------+----------------+----------------+----------------+ -| Type | Decimal(10, 1) | Decimal(76, 2) | Decimal(39, 7) | +| Type | Decimal(10, 1) | Decimal(76, 2) | Decimal(18, 7) | | Domain | {3.1..=188.8} | {0.50..=12.34} | Unknown | | Row 0 | 3.1 | 0.50 | 6.2000000 | | Row 1 | 33.5 | 0.92 | 36.4130435 | @@ -1283,7 +1283,7 @@ evaluation (internal): +--------+-------------------------------------------------+ | e | Decimal128([3.1, 33.5, 188.8]) | | f | Decimal256([0.50, 0.92, 12.34]) | -| Output | Decimal256([6.2000000, 36.4130435, 15.2998379]) | +| Output | Decimal128([6.2000000, 36.4130435, 15.2998379]) | +--------+-------------------------------------------------+ diff --git a/src/query/functions/tests/it/scalars/testdata/arithmetic_decimal.txt b/src/query/functions/tests/it/scalars/testdata/arithmetic_decimal.txt new file mode 100644 index 0000000000000..6631ef63677f4 --- /dev/null +++ b/src/query/functions/tests/it/scalars/testdata/arithmetic_decimal.txt @@ -0,0 +1,31 @@ +ast : l_extendedprice + (1 - l_discount) - l_quantity +raw expr : minus(plus(l_extendedprice::Decimal(15, 2), minus(1, l_discount::Decimal(15, 2))), l_quantity::Decimal(15, 2)) +checked expr : minus(plus(l_extendedprice, minus(1_u8, l_discount)), l_quantity) +evaluation: ++--------+-----------------------+----------------+-----------------+-----------------------+ +| | l_extendedprice | l_discount | l_quantity | Output | ++--------+-----------------------+----------------+-----------------+-----------------------+ +| Type | Decimal(15, 2) | Decimal(15, 2) | Decimal(15, 2) | Decimal(18, 2) | +| Domain | {19411.84..=85768.32} | {0.00..=0.09} | {16.00..=48.00} | {19364.75..=85753.32} | +| Row 0 | 70290.81 | 0.08 | 43.00 | 70248.73 | +| Row 1 | 39880.40 | 0.08 | 40.00 | 39841.32 | +| Row 2 | 26960.83 | 0.00 | 23.00 | 26938.83 | +| Row 3 | 85768.32 | 0.09 | 48.00 | 85721.23 | +| Row 4 | 31790.20 | 0.07 | 20.00 | 31771.13 | +| Row 5 | 19411.84 | 0.07 | 16.00 | 19396.77 | +| Row 6 | 69118.22 | 0.07 | 46.00 | 69073.15 | +| Row 7 | 48748.25 | 0.09 | 25.00 | 48724.16 | +| Row 8 | 42072.70 | 0.09 | 37.00 | 42036.61 | +| Row 9 | 44254.44 | 0.02 | 36.00 | 44219.42 | ++--------+-----------------------+----------------+-----------------+-----------------------+ +evaluation (internal): ++-----------------+------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++-----------------+------------------------------------------------------------------------------------------------------------------+ +| l_extendedprice | Decimal64([70290.81, 39880.40, 26960.83, 85768.32, 31790.20, 19411.84, 69118.22, 48748.25, 42072.70, 44254.44]) | +| l_discount | Decimal64([0.08, 0.08, 0.00, 0.09, 0.07, 0.07, 0.07, 0.09, 0.09, 0.02]) | +| l_quantity | Decimal64([43.00, 40.00, 23.00, 48.00, 20.00, 16.00, 46.00, 25.00, 37.00, 36.00]) | +| Output | Decimal128([70248.73, 39841.32, 26938.83, 85721.23, 31771.13, 19396.77, 69073.15, 48724.16, 42036.61, 44219.42]) | ++-----------------+------------------------------------------------------------------------------------------------------------------+ + + diff --git a/src/query/functions/tests/it/scalars/testdata/decimal_to_decimal_cast.txt b/src/query/functions/tests/it/scalars/testdata/decimal_to_decimal_cast.txt new file mode 100644 index 0000000000000..6fe26bbc9a723 --- /dev/null +++ b/src/query/functions/tests/it/scalars/testdata/decimal_to_decimal_cast.txt @@ -0,0 +1,1491 @@ +ast : CAST(123.45::DECIMAL(5,2) AS DECIMAL(5,2)) +raw expr : CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(5, 2)) +checked expr : 123.45_d128(5,2) +output type : Decimal(5, 2) +output domain : {123.45..=123.45} +output : 123.45 + + +ast : CAST(0.00::DECIMAL(3,2) AS DECIMAL(3,2)) +raw expr : CAST(CAST(0.00 AS Decimal(3, 2)) AS Decimal(3, 2)) +checked expr : CAST(0.00_d128(2,2) AS Decimal(3, 2)) +optimized expr : 0.00_d128(3,2) +output type : Decimal(3, 2) +output domain : {0.00..=0.00} +output : 0.00 + + +ast : CAST(-999.99::DECIMAL(5,2) AS DECIMAL(5,2)) +raw expr : CAST(minus(CAST(999.99 AS Decimal(5, 2))) AS Decimal(5, 2)) +checked expr : minus(999.99_d128(5,2)) +optimized expr : -999.99_d128(5,2) +output type : Decimal(5, 2) +output domain : {-999.99..=-999.99} +output : -999.99 + + +ast : CAST(123.45::DECIMAL(5,2) AS DECIMAL(10,2)) +raw expr : CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(10, 2)) +checked expr : CAST(123.45_d128(5,2) AS Decimal(10, 2)) +optimized expr : 123.45_d128(10,2) +output type : Decimal(10, 2) +output domain : {123.45..=123.45} +output : 123.45 + + +ast : CAST(-123.45::DECIMAL(5,2) AS DECIMAL(15,2)) +raw expr : CAST(minus(CAST(123.45 AS Decimal(5, 2))) AS Decimal(15, 2)) +checked expr : CAST(minus(123.45_d128(5,2)) AS Decimal(15, 2)) +optimized expr : -123.45_d128(15,2) +output type : Decimal(15, 2) +output domain : {-123.45..=-123.45} +output : -123.45 + + +error: + --> SQL:1:1 + | +1 | CAST(123.45::DECIMAL(5,2) AS DECIMAL(5,4)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 881 while evaluating function `to_decimal(5, 4)(123.45)` in expr `CAST(123.45 AS Decimal(5, 4))` + + + +error: + --> SQL:1:1 + | +1 | CAST(123::DECIMAL(3,0) AS DECIMAL(3,2)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 881 while evaluating function `to_decimal(3, 2)(123)` in expr `CAST(CAST(123 AS Decimal(3, 0)) AS Decimal(3, 2))` + + + +ast : CAST(123.45::DECIMAL(5,2) AS DECIMAL(10,4)) +raw expr : CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(10, 4)) +checked expr : CAST(123.45_d128(5,2) AS Decimal(10, 4)) +optimized expr : 123.4500_d128(10,4) +output type : Decimal(10, 4) +output domain : {123.4500..=123.4500} +output : 123.4500 + + +ast : CAST(1.2::DECIMAL(2,1) AS DECIMAL(20,10)) +raw expr : CAST(CAST(1.2 AS Decimal(2, 1)) AS Decimal(20, 10)) +checked expr : CAST(1.2_d128(2,1) AS Decimal(20, 10)) +optimized expr : 1.2000000000_d128(20,10) +output type : Decimal(20, 10) +output domain : {1.2000000000..=1.2000000000} +output : 1.2000000000 + + +ast : CAST(0::DECIMAL(1,0) AS DECIMAL(10,5)) +raw expr : CAST(CAST(0 AS Decimal(1, 0)) AS Decimal(10, 5)) +checked expr : CAST(CAST(0_u8 AS Decimal(1, 0)) AS Decimal(10, 5)) +optimized expr : 0.00000_d128(10,5) +output type : Decimal(10, 5) +output domain : {0.00000..=0.00000} +output : 0.00000 + + +ast : CAST(0.00000::DECIMAL(6,5) AS DECIMAL(2,1)) +raw expr : CAST(CAST(0.00000 AS Decimal(6, 5)) AS Decimal(2, 1)) +checked expr : CAST(CAST(0.00000_d128(5,5) AS Decimal(6, 5)) AS Decimal(2, 1)) +optimized expr : 0.0_d128(2,1) +output type : Decimal(2, 1) +output domain : {0.0..=0.0} +output : 0.0 + + +ast : CAST(123.456::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : CAST(CAST(123.456 AS Decimal(6, 3)) AS Decimal(6, 1)) +checked expr : CAST(123.456_d128(6,3) AS Decimal(6, 1)) +optimized expr : 123.5_d128(6,1) +func ctx : (modified) +output type : Decimal(6, 1) +output domain : {123.5..=123.5} +output : 123.5 + + +ast : CAST(123.999::DECIMAL(6,3) AS DECIMAL(6,2)) +raw expr : CAST(CAST(123.999 AS Decimal(6, 3)) AS Decimal(6, 2)) +checked expr : CAST(123.999_d128(6,3) AS Decimal(6, 2)) +optimized expr : 124.00_d128(6,2) +func ctx : (modified) +output type : Decimal(6, 2) +output domain : {124.00..=124.00} +output : 124.00 + + +ast : CAST(999.995::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : CAST(CAST(999.995 AS Decimal(6, 3)) AS Decimal(6, 1)) +checked expr : CAST(999.995_d128(6,3) AS Decimal(6, 1)) +optimized expr : 1000.0_d128(6,1) +func ctx : (modified) +output type : Decimal(6, 1) +output domain : {1000.0..=1000.0} +output : 1000.0 + + +ast : CAST(12.345::DECIMAL(5,3) AS DECIMAL(5,0)) +raw expr : CAST(CAST(12.345 AS Decimal(5, 3)) AS Decimal(5, 0)) +checked expr : CAST(12.345_d128(5,3) AS Decimal(5, 0)) +optimized expr : 12_d128(5,0) +func ctx : (modified) +output type : Decimal(5, 0) +output domain : {12..=12} +output : 12 + + +ast : CAST(12.567::DECIMAL(5,3) AS DECIMAL(5,1)) +raw expr : CAST(CAST(12.567 AS Decimal(5, 3)) AS Decimal(5, 1)) +checked expr : CAST(12.567_d128(5,3) AS Decimal(5, 1)) +optimized expr : 12.6_d128(5,1) +func ctx : (modified) +output type : Decimal(5, 1) +output domain : {12.6..=12.6} +output : 12.6 + + +ast : CAST(-12.345::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : CAST(minus(CAST(12.345 AS Decimal(6, 3))) AS Decimal(6, 1)) +checked expr : CAST(minus(CAST(12.345_d128(5,3) AS Decimal(6, 3))) AS Decimal(6, 1)) +optimized expr : -12.3_d128(6,1) +func ctx : (modified) +output type : Decimal(6, 1) +output domain : {-12.3..=-12.3} +output : -12.3 + + +ast : CAST(-12.567::DECIMAL(6,3) AS DECIMAL(6,2)) +raw expr : CAST(minus(CAST(12.567 AS Decimal(6, 3))) AS Decimal(6, 2)) +checked expr : CAST(minus(CAST(12.567_d128(5,3) AS Decimal(6, 3))) AS Decimal(6, 2)) +optimized expr : -12.57_d128(6,2) +func ctx : (modified) +output type : Decimal(6, 2) +output domain : {-12.57..=-12.57} +output : -12.57 + + +ast : CAST(0.999::DECIMAL(4,3) AS DECIMAL(4,0)) +raw expr : CAST(CAST(0.999 AS Decimal(4, 3)) AS Decimal(4, 0)) +checked expr : CAST(CAST(0.999_d128(3,3) AS Decimal(4, 3)) AS Decimal(4, 0)) +optimized expr : 1_d128(4,0) +func ctx : (modified) +output type : Decimal(4, 0) +output domain : {1..=1} +output : 1 + + +ast : CAST(0.001::DECIMAL(4,3) AS DECIMAL(4,1)) +raw expr : CAST(CAST(0.001 AS Decimal(4, 3)) AS Decimal(4, 1)) +checked expr : CAST(CAST(0.001_d128(3,3) AS Decimal(4, 3)) AS Decimal(4, 1)) +optimized expr : 0.0_d128(4,1) +func ctx : (modified) +output type : Decimal(4, 1) +output domain : {0.0..=0.0} +output : 0.0 + + +ast : CAST(c AS DECIMAL(8,0)) +raw expr : CAST(c::Decimal(8, 3) AS Decimal(8, 0)) +checked expr : CAST(c AS Decimal(8, 0)) +func ctx : (modified) +evaluation: ++--------+---------------------+---------------+ +| | c | Output | ++--------+---------------------+---------------+ +| Type | Decimal(8, 3) | Decimal(8, 0) | +| Domain | {-99.999..=123.456} | {-100..=123} | +| Row 0 | 12.345 | 12 | +| Row 1 | 67.890 | 68 | +| Row 2 | -11.111 | -11 | +| Row 3 | 99.999 | 100 | +| Row 4 | 0.000 | 0 | +| Row 5 | -99.999 | -100 | +| Row 6 | 123.456 | 123 | ++--------+---------------------+---------------+ +evaluation (internal): ++--------+------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | Decimal128([12, 68, -11, 100, 0, -100, 123]) | ++--------+------------------------------------------------------------------------+ + + +ast : CAST(c AS DECIMAL(8,1)) +raw expr : CAST(c::Decimal(8, 3) AS Decimal(8, 1)) +checked expr : CAST(c AS Decimal(8, 1)) +func ctx : (modified) +evaluation: ++--------+---------------------+------------------+ +| | c | Output | ++--------+---------------------+------------------+ +| Type | Decimal(8, 3) | Decimal(8, 1) | +| Domain | {-99.999..=123.456} | {-100.0..=123.5} | +| Row 0 | 12.345 | 12.3 | +| Row 1 | 67.890 | 67.9 | +| Row 2 | -11.111 | -11.1 | +| Row 3 | 99.999 | 100.0 | +| Row 4 | 0.000 | 0.0 | +| Row 5 | -99.999 | -100.0 | +| Row 6 | 123.456 | 123.5 | ++--------+---------------------+------------------+ +evaluation (internal): ++--------+------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | Decimal128([12.3, 67.9, -11.1, 100.0, 0.0, -100.0, 123.5]) | ++--------+------------------------------------------------------------------------+ + + +ast : CAST(c AS DECIMAL(8,2)) +raw expr : CAST(c::Decimal(8, 3) AS Decimal(8, 2)) +checked expr : CAST(c AS Decimal(8, 2)) +func ctx : (modified) +evaluation: ++--------+---------------------+--------------------+ +| | c | Output | ++--------+---------------------+--------------------+ +| Type | Decimal(8, 3) | Decimal(8, 2) | +| Domain | {-99.999..=123.456} | {-100.00..=123.46} | +| Row 0 | 12.345 | 12.35 | +| Row 1 | 67.890 | 67.89 | +| Row 2 | -11.111 | -11.11 | +| Row 3 | 99.999 | 100.00 | +| Row 4 | 0.000 | 0.00 | +| Row 5 | -99.999 | -100.00 | +| Row 6 | 123.456 | 123.46 | ++--------+---------------------+--------------------+ +evaluation (internal): ++--------+------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | Decimal128([12.35, 67.89, -11.11, 100.00, 0.00, -100.00, 123.46]) | ++--------+------------------------------------------------------------------------+ + + +ast : CAST(123.456::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : CAST(CAST(123.456 AS Decimal(6, 3)) AS Decimal(6, 1)) +checked expr : CAST(123.456_d128(6,3) AS Decimal(6, 1)) +optimized expr : 123.4_d128(6,1) +output type : Decimal(6, 1) +output domain : {123.4..=123.4} +output : 123.4 + + +ast : CAST(123.999::DECIMAL(6,3) AS DECIMAL(6,2)) +raw expr : CAST(CAST(123.999 AS Decimal(6, 3)) AS Decimal(6, 2)) +checked expr : CAST(123.999_d128(6,3) AS Decimal(6, 2)) +optimized expr : 123.99_d128(6,2) +output type : Decimal(6, 2) +output domain : {123.99..=123.99} +output : 123.99 + + +ast : CAST(999.995::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : CAST(CAST(999.995 AS Decimal(6, 3)) AS Decimal(6, 1)) +checked expr : CAST(999.995_d128(6,3) AS Decimal(6, 1)) +optimized expr : 999.9_d128(6,1) +output type : Decimal(6, 1) +output domain : {999.9..=999.9} +output : 999.9 + + +ast : CAST(12.345::DECIMAL(5,3) AS DECIMAL(5,0)) +raw expr : CAST(CAST(12.345 AS Decimal(5, 3)) AS Decimal(5, 0)) +checked expr : CAST(12.345_d128(5,3) AS Decimal(5, 0)) +optimized expr : 12_d128(5,0) +output type : Decimal(5, 0) +output domain : {12..=12} +output : 12 + + +ast : CAST(12.567::DECIMAL(5,3) AS DECIMAL(5,1)) +raw expr : CAST(CAST(12.567 AS Decimal(5, 3)) AS Decimal(5, 1)) +checked expr : CAST(12.567_d128(5,3) AS Decimal(5, 1)) +optimized expr : 12.5_d128(5,1) +output type : Decimal(5, 1) +output domain : {12.5..=12.5} +output : 12.5 + + +ast : CAST(-12.345::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : CAST(minus(CAST(12.345 AS Decimal(6, 3))) AS Decimal(6, 1)) +checked expr : CAST(minus(CAST(12.345_d128(5,3) AS Decimal(6, 3))) AS Decimal(6, 1)) +optimized expr : -12.3_d128(6,1) +output type : Decimal(6, 1) +output domain : {-12.3..=-12.3} +output : -12.3 + + +ast : CAST(-12.567::DECIMAL(6,3) AS DECIMAL(6,2)) +raw expr : CAST(minus(CAST(12.567 AS Decimal(6, 3))) AS Decimal(6, 2)) +checked expr : CAST(minus(CAST(12.567_d128(5,3) AS Decimal(6, 3))) AS Decimal(6, 2)) +optimized expr : -12.56_d128(6,2) +output type : Decimal(6, 2) +output domain : {-12.56..=-12.56} +output : -12.56 + + +ast : CAST(0.999::DECIMAL(4,3) AS DECIMAL(4,0)) +raw expr : CAST(CAST(0.999 AS Decimal(4, 3)) AS Decimal(4, 0)) +checked expr : CAST(CAST(0.999_d128(3,3) AS Decimal(4, 3)) AS Decimal(4, 0)) +optimized expr : 0_d128(4,0) +output type : Decimal(4, 0) +output domain : {0..=0} +output : 0 + + +ast : CAST(0.001::DECIMAL(4,3) AS DECIMAL(4,1)) +raw expr : CAST(CAST(0.001 AS Decimal(4, 3)) AS Decimal(4, 1)) +checked expr : CAST(CAST(0.001_d128(3,3) AS Decimal(4, 3)) AS Decimal(4, 1)) +optimized expr : 0.0_d128(4,1) +output type : Decimal(4, 1) +output domain : {0.0..=0.0} +output : 0.0 + + +ast : CAST(c AS DECIMAL(8,0)) +raw expr : CAST(c::Decimal(8, 3) AS Decimal(8, 0)) +checked expr : CAST(c AS Decimal(8, 0)) +evaluation: ++--------+---------------------+---------------+ +| | c | Output | ++--------+---------------------+---------------+ +| Type | Decimal(8, 3) | Decimal(8, 0) | +| Domain | {-99.999..=123.456} | {-99..=123} | +| Row 0 | 12.345 | 12 | +| Row 1 | 67.890 | 67 | +| Row 2 | -11.111 | -11 | +| Row 3 | 99.999 | 99 | +| Row 4 | 0.000 | 0 | +| Row 5 | -99.999 | -99 | +| Row 6 | 123.456 | 123 | ++--------+---------------------+---------------+ +evaluation (internal): ++--------+------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | Decimal128([12, 67, -11, 99, 0, -99, 123]) | ++--------+------------------------------------------------------------------------+ + + +ast : CAST(c AS DECIMAL(8,1)) +raw expr : CAST(c::Decimal(8, 3) AS Decimal(8, 1)) +checked expr : CAST(c AS Decimal(8, 1)) +evaluation: ++--------+---------------------+-----------------+ +| | c | Output | ++--------+---------------------+-----------------+ +| Type | Decimal(8, 3) | Decimal(8, 1) | +| Domain | {-99.999..=123.456} | {-99.9..=123.4} | +| Row 0 | 12.345 | 12.3 | +| Row 1 | 67.890 | 67.8 | +| Row 2 | -11.111 | -11.1 | +| Row 3 | 99.999 | 99.9 | +| Row 4 | 0.000 | 0.0 | +| Row 5 | -99.999 | -99.9 | +| Row 6 | 123.456 | 123.4 | ++--------+---------------------+-----------------+ +evaluation (internal): ++--------+------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | Decimal128([12.3, 67.8, -11.1, 99.9, 0.0, -99.9, 123.4]) | ++--------+------------------------------------------------------------------------+ + + +ast : CAST(c AS DECIMAL(8,2)) +raw expr : CAST(c::Decimal(8, 3) AS Decimal(8, 2)) +checked expr : CAST(c AS Decimal(8, 2)) +evaluation: ++--------+---------------------+-------------------+ +| | c | Output | ++--------+---------------------+-------------------+ +| Type | Decimal(8, 3) | Decimal(8, 2) | +| Domain | {-99.999..=123.456} | {-99.99..=123.45} | +| Row 0 | 12.345 | 12.34 | +| Row 1 | 67.890 | 67.89 | +| Row 2 | -11.111 | -11.11 | +| Row 3 | 99.999 | 99.99 | +| Row 4 | 0.000 | 0.00 | +| Row 5 | -99.999 | -99.99 | +| Row 6 | 123.456 | 123.45 | ++--------+---------------------+-------------------+ +evaluation (internal): ++--------+------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | Decimal128([12.34, 67.89, -11.11, 99.99, 0.00, -99.99, 123.45]) | ++--------+------------------------------------------------------------------------+ + + +error: + --> SQL:1:1 + | +1 | CAST(12345.67::DECIMAL(7,2) AS DECIMAL(5,2)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 881 while evaluating function `to_decimal(5, 2)(12345.67)` in expr `CAST(12345.67 AS Decimal(5, 2))` + + + +error: + --> SQL:1:1 + | +1 | CAST(999.99::DECIMAL(5,2) AS DECIMAL(4,2)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 881 while evaluating function `to_decimal(4, 2)(999.99)` in expr `CAST(999.99 AS Decimal(4, 2))` + + + +error: + --> SQL:1:1 + | +1 | CAST(99.9::DECIMAL(3,1) AS DECIMAL(2,1)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 881 while evaluating function `to_decimal(2, 1)(99.9)` in expr `CAST(99.9 AS Decimal(2, 1))` + + + +ast : CAST(-999.999::DECIMAL(6,3) AS DECIMAL(4,1)) +raw expr : CAST(minus(CAST(999.999 AS Decimal(6, 3))) AS Decimal(4, 1)) +checked expr : CAST(minus(999.999_d128(6,3)) AS Decimal(4, 1)) +optimized expr : -999.9_d128(4,1) +output type : Decimal(4, 1) +output domain : {-999.9..=-999.9} +output : -999.9 + + +error: + --> SQL:1:1 + | +1 | CAST(-123.45::DECIMAL(5,2) AS DECIMAL(4,2)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 881 while evaluating function `to_decimal(4, 2)(-123.45)` in expr `CAST(- 123.45 AS Decimal(4, 2))` + + + +error: + --> SQL:1:1 + | +1 | CAST(99.99::DECIMAL(4,2) AS DECIMAL(3,2)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 881 while evaluating function `to_decimal(3, 2)(99.99)` in expr `CAST(99.99 AS Decimal(3, 2))` + + + +error: + --> SQL:1:1 + | +1 | CAST(9.99::DECIMAL(3,2) AS DECIMAL(2,2)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 881 while evaluating function `to_decimal(2, 2)(9.99)` in expr `CAST(9.99 AS Decimal(2, 2))` + + + +ast : CAST(123.45::DECIMAL(5,2) AS DECIMAL(38,10)) +raw expr : CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(38, 10)) +checked expr : CAST(123.45_d128(5,2) AS Decimal(38, 10)) +optimized expr : 123.4500000000_d128(38,10) +output type : Decimal(38, 10) +output domain : {123.4500000000..=123.4500000000} +output : 123.4500000000 + + +ast : CAST(123456789.123456789::DECIMAL(18,9) AS DECIMAL(38,20)) +raw expr : CAST(CAST(123456789.123456789 AS Decimal(18, 9)) AS Decimal(38, 20)) +checked expr : CAST(123456789.123456789_d128(18,9) AS Decimal(38, 20)) +optimized expr : 123456789.12345678900000000000_d128(38,20) +output type : Decimal(38, 20) +output domain : {123456789.12345678900000000000..=123456789.12345678900000000000} +output : 123456789.12345678900000000000 + + +error: + --> SQL:1:1 + | +1 | CAST(12345678901234567890.123456789::DECIMAL(38,9) AS DECIMAL(18,4)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 860 while evaluating function `to_decimal(18, 4)(12345678901234567890.123456789)` in expr `CAST(CAST(12345678901234567890.123456789 AS Decimal(38, 9)) AS Decimal(18, 4))` + + + +ast : CAST(99.99::DECIMAL(4,2) AS DECIMAL(6,2)) +raw expr : CAST(CAST(99.99 AS Decimal(4, 2)) AS Decimal(6, 2)) +checked expr : CAST(99.99_d128(4,2) AS Decimal(6, 2)) +optimized expr : 99.99_d128(6,2) +output type : Decimal(6, 2) +output domain : {99.99..=99.99} +output : 99.99 + + +ast : CAST(999999.999::DECIMAL(9,3) AS DECIMAL(15,6)) +raw expr : CAST(CAST(999999.999 AS Decimal(9, 3)) AS Decimal(15, 6)) +checked expr : CAST(999999.999_d128(9,3) AS Decimal(15, 6)) +optimized expr : 999999.999000_d128(15,6) +output type : Decimal(15, 6) +output domain : {999999.999000..=999999.999000} +output : 999999.999000 + + +ast : CAST(a AS DECIMAL(15,3)) +raw expr : CAST(a::Decimal(10, 2) AS Decimal(15, 3)) +checked expr : CAST(a AS Decimal(15, 3)) +evaluation: ++--------+----------------------------+------------------------------+ +| | a | Output | ++--------+----------------------------+------------------------------+ +| Type | Decimal(10, 2) | Decimal(15, 3) | +| Domain | {-9876543.21..=1234567.89} | {-9876543.210..=1234567.890} | +| Row 0 | 0.00 | 0.000 | +| Row 1 | 0.01 | 0.010 | +| Row 2 | -0.01 | -0.010 | +| Row 3 | 1234567.89 | 1234567.890 | +| Row 4 | -9876543.21 | -9876543.210 | +| Row 5 | 9999.99 | 9999.990 | ++--------+----------------------------+------------------------------+ +evaluation (internal): ++--------+-------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------+ +| a | Decimal128([0.00, 0.01, -0.01, 1234567.89, -9876543.21, 9999.99]) | +| Output | Decimal128([0.000, 0.010, -0.010, 1234567.890, -9876543.210, 9999.990]) | ++--------+-------------------------------------------------------------------------+ + + +ast : CAST(a AS DECIMAL(20,5)) +raw expr : CAST(a::Decimal(10, 2) AS Decimal(20, 5)) +checked expr : CAST(a AS Decimal(20, 5)) +evaluation: ++--------+----------------------------+----------------------------------+ +| | a | Output | ++--------+----------------------------+----------------------------------+ +| Type | Decimal(10, 2) | Decimal(20, 5) | +| Domain | {-9876543.21..=1234567.89} | {-9876543.21000..=1234567.89000} | +| Row 0 | 0.00 | 0.00000 | +| Row 1 | 0.01 | 0.01000 | +| Row 2 | -0.01 | -0.01000 | +| Row 3 | 1234567.89 | 1234567.89000 | +| Row 4 | -9876543.21 | -9876543.21000 | +| Row 5 | 9999.99 | 9999.99000 | ++--------+----------------------------+----------------------------------+ +evaluation (internal): ++--------+-------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------------------+ +| a | Decimal128([0.00, 0.01, -0.01, 1234567.89, -9876543.21, 9999.99]) | +| Output | Decimal128([0.00000, 0.01000, -0.01000, 1234567.89000, -9876543.21000, 9999.99000]) | ++--------+-------------------------------------------------------------------------------------+ + + +ast : CAST(b AS DECIMAL(10,2)) +raw expr : CAST(b::Decimal(15, 3) AS Decimal(10, 2)) +checked expr : CAST(b AS Decimal(10, 2)) +evaluation: ++--------+----------------------------+--------------------------+ +| | b | Output | ++--------+----------------------------+--------------------------+ +| Type | Decimal(15, 3) | Decimal(10, 2) | +| Domain | {-987654.320..=123456.780} | {-987654.32..=123456.78} | +| Row 0 | 0.000 | 0.00 | +| Row 1 | 0.002 | 0.00 | +| Row 2 | -0.002 | 0.00 | +| Row 3 | 123456.780 | 123456.78 | +| Row 4 | -987654.320 | -987654.32 | +| Row 5 | 1000.000 | 1000.00 | ++--------+----------------------------+--------------------------+ +evaluation (internal): ++--------+-----------------------------------------------------------------------+ +| Column | Data | ++--------+-----------------------------------------------------------------------+ +| b | Decimal256([0.000, 0.002, -0.002, 123456.780, -987654.320, 1000.000]) | +| Output | Decimal128([0.00, 0.00, 0.00, 123456.78, -987654.32, 1000.00]) | ++--------+-----------------------------------------------------------------------+ + + +ast : CAST(b AS DECIMAL(38,10)) +raw expr : CAST(b::Decimal(15, 3) AS Decimal(38, 10)) +checked expr : CAST(b AS Decimal(38, 10)) +evaluation: ++--------+----------------------------+------------------------------------------+ +| | b | Output | ++--------+----------------------------+------------------------------------------+ +| Type | Decimal(15, 3) | Decimal(38, 10) | +| Domain | {-987654.320..=123456.780} | {-987654.3200000000..=123456.7800000000} | +| Row 0 | 0.000 | 0.0000000000 | +| Row 1 | 0.002 | 0.0020000000 | +| Row 2 | -0.002 | -0.0020000000 | +| Row 3 | 123456.780 | 123456.7800000000 | +| Row 4 | -987654.320 | -987654.3200000000 | +| Row 5 | 1000.000 | 1000.0000000000 | ++--------+----------------------------+------------------------------------------+ +evaluation (internal): ++--------+-----------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-----------------------------------------------------------------------------------------------------------------+ +| b | Decimal256([0.000, 0.002, -0.002, 123456.780, -987654.320, 1000.000]) | +| Output | Decimal128([0.0000000000, 0.0020000000, -0.0020000000, 123456.7800000000, -987654.3200000000, 1000.0000000000]) | ++--------+-----------------------------------------------------------------------------------------------------------------+ + + +error: + --> SQL:1:1 + | +1 | CAST(a AS DECIMAL(5,1)) + | ^^^^^^^^^^^^^^^^^^^^^^^ Decimal overflow at line : 860 while evaluating function `to_decimal(5, 1)(1234567.89)` in expr `CAST(a AS Decimal(5, 1))` + + + +ast : CAST(b AS DECIMAL(8,2)) +raw expr : CAST(b::Decimal(15, 3) AS Decimal(8, 2)) +checked expr : CAST(b AS Decimal(8, 2)) +evaluation: ++--------+----------------------------+--------------------------+ +| | b | Output | ++--------+----------------------------+--------------------------+ +| Type | Decimal(15, 3) | Decimal(8, 2) | +| Domain | {-987654.320..=123456.780} | {-987654.32..=123456.78} | +| Row 0 | 0.000 | 0.00 | +| Row 1 | 0.002 | 0.00 | +| Row 2 | -0.002 | 0.00 | +| Row 3 | 123456.780 | 123456.78 | +| Row 4 | -987654.320 | -987654.32 | +| Row 5 | 1000.000 | 1000.00 | ++--------+----------------------------+--------------------------+ +evaluation (internal): ++--------+-----------------------------------------------------------------------+ +| Column | Data | ++--------+-----------------------------------------------------------------------+ +| b | Decimal256([0.000, 0.002, -0.002, 123456.780, -987654.320, 1000.000]) | +| Output | Decimal128([0.00, 0.00, 0.00, 123456.78, -987654.32, 1000.00]) | ++--------+-----------------------------------------------------------------------+ + + +ast : CAST(d AS DECIMAL(20,5)) +raw expr : CAST(d::Decimal(38, 10) AS Decimal(20, 5)) +checked expr : CAST(d AS Decimal(20, 5)) +evaluation: ++--------+----------------------------------------------+------------------------------------+ +| | d | Output | ++--------+----------------------------------------------+------------------------------------+ +| Type | Decimal(38, 10) | Decimal(20, 5) | +| Domain | {-99999999.9999999999..=99999999.9999999999} | {-99999999.99999..=99999999.99999} | +| Row 0 | 99999999.9999999999 | 99999999.99999 | +| Row 1 | -99999999.9999999999 | -99999999.99999 | +| Row 2 | 0.0000000000 | 0.00000 | +| Row 3 | 12345.6789012345 | 12345.67890 | +| Row 4 | -12345.6789012345 | -12345.67890 | ++--------+----------------------------------------------+------------------------------------+ +evaluation (internal): ++--------+------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------------------------------------------+ +| d | Decimal256([99999999.9999999999, -99999999.9999999999, 0.0000000000, 12345.6789012345, -12345.6789012345]) | +| Output | Decimal128([99999999.99999, -99999999.99999, 0.00000, 12345.67890, -12345.67890]) | ++--------+------------------------------------------------------------------------------------------------------------+ + + +ast : CAST(d AS DECIMAL(38,15)) +raw expr : CAST(d::Decimal(38, 10) AS Decimal(38, 15)) +checked expr : CAST(d AS Decimal(38, 15)) +evaluation: ++--------+----------------------------------------------+--------------------------------------------------------+ +| | d | Output | ++--------+----------------------------------------------+--------------------------------------------------------+ +| Type | Decimal(38, 10) | Decimal(38, 15) | +| Domain | {-99999999.9999999999..=99999999.9999999999} | {-99999999.999999999900000..=99999999.999999999900000} | +| Row 0 | 99999999.9999999999 | 99999999.999999999900000 | +| Row 1 | -99999999.9999999999 | -99999999.999999999900000 | +| Row 2 | 0.0000000000 | 0.000000000000000 | +| Row 3 | 12345.6789012345 | 12345.678901234500000 | +| Row 4 | -12345.6789012345 | -12345.678901234500000 | ++--------+----------------------------------------------+--------------------------------------------------------+ +evaluation (internal): ++--------+-------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------------------------------------------------------------------+ +| d | Decimal256([99999999.9999999999, -99999999.9999999999, 0.0000000000, 12345.6789012345, -12345.6789012345]) | +| Output | Decimal128([99999999.999999999900000, -99999999.999999999900000, 0.000000000000000, 12345.678901234500000, -12345.678901234500000]) | ++--------+-------------------------------------------------------------------------------------------------------------------------------------+ + + +ast : CAST(d AS DECIMAL(15,2)) +raw expr : CAST(d::Decimal(38, 10) AS Decimal(15, 2)) +checked expr : CAST(d AS Decimal(15, 2)) +evaluation: ++--------+----------------------------------------------+------------------------------+ +| | d | Output | ++--------+----------------------------------------------+------------------------------+ +| Type | Decimal(38, 10) | Decimal(15, 2) | +| Domain | {-99999999.9999999999..=99999999.9999999999} | {-99999999.99..=99999999.99} | +| Row 0 | 99999999.9999999999 | 99999999.99 | +| Row 1 | -99999999.9999999999 | -99999999.99 | +| Row 2 | 0.0000000000 | 0.00 | +| Row 3 | 12345.6789012345 | 12345.67 | +| Row 4 | -12345.6789012345 | -12345.67 | ++--------+----------------------------------------------+------------------------------+ +evaluation (internal): ++--------+------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------------------------------------------+ +| d | Decimal256([99999999.9999999999, -99999999.9999999999, 0.0000000000, 12345.6789012345, -12345.6789012345]) | +| Output | Decimal128([99999999.99, -99999999.99, 0.00, 12345.67, -12345.67]) | ++--------+------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(123.45::DECIMAL(5,2) AS DECIMAL(5,2)) +raw expr : TRY_CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(5, 2)) +checked expr : TRY_CAST(123.45_d128(5,2) AS Decimal(5, 2) NULL) +optimized expr : 123.45_d128(5,2) +output type : Decimal(5, 2) NULL +output domain : {123.45..=123.45} +output : 123.45 + + +ast : TRY_CAST(0.00::DECIMAL(3,2) AS DECIMAL(3,2)) +raw expr : TRY_CAST(CAST(0.00 AS Decimal(3, 2)) AS Decimal(3, 2)) +checked expr : TRY_CAST(CAST(0.00_d128(2,2) AS Decimal(3, 2)) AS Decimal(3, 2) NULL) +optimized expr : 0.00_d128(3,2) +output type : Decimal(3, 2) NULL +output domain : {0.00..=0.00} +output : 0.00 + + +ast : TRY_CAST(-999.99::DECIMAL(5,2) AS DECIMAL(5,2)) +raw expr : TRY_CAST(minus(CAST(999.99 AS Decimal(5, 2))) AS Decimal(5, 2)) +checked expr : TRY_CAST(minus(999.99_d128(5,2)) AS Decimal(5, 2) NULL) +optimized expr : -999.99_d128(5,2) +output type : Decimal(5, 2) NULL +output domain : {-999.99..=-999.99} +output : -999.99 + + +ast : TRY_CAST(123.45::DECIMAL(5,2) AS DECIMAL(10,2)) +raw expr : TRY_CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(10, 2)) +checked expr : TRY_CAST(123.45_d128(5,2) AS Decimal(10, 2) NULL) +optimized expr : 123.45_d128(10,2) +output type : Decimal(10, 2) NULL +output domain : {123.45..=123.45} +output : 123.45 + + +ast : TRY_CAST(-123.45::DECIMAL(5,2) AS DECIMAL(15,2)) +raw expr : TRY_CAST(minus(CAST(123.45 AS Decimal(5, 2))) AS Decimal(15, 2)) +checked expr : TRY_CAST(minus(123.45_d128(5,2)) AS Decimal(15, 2) NULL) +optimized expr : -123.45_d128(15,2) +output type : Decimal(15, 2) NULL +output domain : {-123.45..=-123.45} +output : -123.45 + + +ast : TRY_CAST(123.45::DECIMAL(5,2) AS DECIMAL(5,4)) +raw expr : TRY_CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(5, 4)) +checked expr : TRY_CAST(123.45_d128(5,2) AS Decimal(5, 4) NULL) +optimized expr : NULL +output type : Decimal(5, 4) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(123::DECIMAL(3,0) AS DECIMAL(3,2)) +raw expr : TRY_CAST(CAST(123 AS Decimal(3, 0)) AS Decimal(3, 2)) +checked expr : TRY_CAST(CAST(123_u8 AS Decimal(3, 0)) AS Decimal(3, 2) NULL) +optimized expr : NULL +output type : Decimal(3, 2) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(123.45::DECIMAL(5,2) AS DECIMAL(10,4)) +raw expr : TRY_CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(10, 4)) +checked expr : TRY_CAST(123.45_d128(5,2) AS Decimal(10, 4) NULL) +optimized expr : 123.4500_d128(10,4) +output type : Decimal(10, 4) NULL +output domain : {123.4500..=123.4500} +output : 123.4500 + + +ast : TRY_CAST(1.2::DECIMAL(2,1) AS DECIMAL(20,10)) +raw expr : TRY_CAST(CAST(1.2 AS Decimal(2, 1)) AS Decimal(20, 10)) +checked expr : TRY_CAST(1.2_d128(2,1) AS Decimal(20, 10) NULL) +optimized expr : 1.2000000000_d128(20,10) +output type : Decimal(20, 10) NULL +output domain : {1.2000000000..=1.2000000000} +output : 1.2000000000 + + +ast : TRY_CAST(0::DECIMAL(1,0) AS DECIMAL(10,5)) +raw expr : TRY_CAST(CAST(0 AS Decimal(1, 0)) AS Decimal(10, 5)) +checked expr : TRY_CAST(CAST(0_u8 AS Decimal(1, 0)) AS Decimal(10, 5) NULL) +optimized expr : 0.00000_d128(10,5) +output type : Decimal(10, 5) NULL +output domain : {0.00000..=0.00000} +output : 0.00000 + + +ast : TRY_CAST(0.00000::DECIMAL(6,5) AS DECIMAL(2,1)) +raw expr : TRY_CAST(CAST(0.00000 AS Decimal(6, 5)) AS Decimal(2, 1)) +checked expr : TRY_CAST(CAST(0.00000_d128(5,5) AS Decimal(6, 5)) AS Decimal(2, 1) NULL) +optimized expr : 0.0_d128(2,1) +output type : Decimal(2, 1) NULL +output domain : {0.0..=0.0} +output : 0.0 + + +ast : TRY_CAST(123.456::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : TRY_CAST(CAST(123.456 AS Decimal(6, 3)) AS Decimal(6, 1)) +checked expr : TRY_CAST(123.456_d128(6,3) AS Decimal(6, 1) NULL) +optimized expr : 123.5_d128(6,1) +func ctx : (modified) +output type : Decimal(6, 1) NULL +output domain : {123.5..=123.5} +output : 123.5 + + +ast : TRY_CAST(123.999::DECIMAL(6,3) AS DECIMAL(6,2)) +raw expr : TRY_CAST(CAST(123.999 AS Decimal(6, 3)) AS Decimal(6, 2)) +checked expr : TRY_CAST(123.999_d128(6,3) AS Decimal(6, 2) NULL) +optimized expr : 124.00_d128(6,2) +func ctx : (modified) +output type : Decimal(6, 2) NULL +output domain : {124.00..=124.00} +output : 124.00 + + +ast : TRY_CAST(999.995::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : TRY_CAST(CAST(999.995 AS Decimal(6, 3)) AS Decimal(6, 1)) +checked expr : TRY_CAST(999.995_d128(6,3) AS Decimal(6, 1) NULL) +optimized expr : 1000.0_d128(6,1) +func ctx : (modified) +output type : Decimal(6, 1) NULL +output domain : {1000.0..=1000.0} +output : 1000.0 + + +ast : TRY_CAST(12.345::DECIMAL(5,3) AS DECIMAL(5,0)) +raw expr : TRY_CAST(CAST(12.345 AS Decimal(5, 3)) AS Decimal(5, 0)) +checked expr : TRY_CAST(12.345_d128(5,3) AS Decimal(5, 0) NULL) +optimized expr : 12_d128(5,0) +func ctx : (modified) +output type : Decimal(5, 0) NULL +output domain : {12..=12} +output : 12 + + +ast : TRY_CAST(12.567::DECIMAL(5,3) AS DECIMAL(5,1)) +raw expr : TRY_CAST(CAST(12.567 AS Decimal(5, 3)) AS Decimal(5, 1)) +checked expr : TRY_CAST(12.567_d128(5,3) AS Decimal(5, 1) NULL) +optimized expr : 12.6_d128(5,1) +func ctx : (modified) +output type : Decimal(5, 1) NULL +output domain : {12.6..=12.6} +output : 12.6 + + +ast : TRY_CAST(-12.345::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : TRY_CAST(minus(CAST(12.345 AS Decimal(6, 3))) AS Decimal(6, 1)) +checked expr : TRY_CAST(minus(CAST(12.345_d128(5,3) AS Decimal(6, 3))) AS Decimal(6, 1) NULL) +optimized expr : -12.3_d128(6,1) +func ctx : (modified) +output type : Decimal(6, 1) NULL +output domain : {-12.3..=-12.3} +output : -12.3 + + +ast : TRY_CAST(-12.567::DECIMAL(6,3) AS DECIMAL(6,2)) +raw expr : TRY_CAST(minus(CAST(12.567 AS Decimal(6, 3))) AS Decimal(6, 2)) +checked expr : TRY_CAST(minus(CAST(12.567_d128(5,3) AS Decimal(6, 3))) AS Decimal(6, 2) NULL) +optimized expr : -12.57_d128(6,2) +func ctx : (modified) +output type : Decimal(6, 2) NULL +output domain : {-12.57..=-12.57} +output : -12.57 + + +ast : TRY_CAST(0.999::DECIMAL(4,3) AS DECIMAL(4,0)) +raw expr : TRY_CAST(CAST(0.999 AS Decimal(4, 3)) AS Decimal(4, 0)) +checked expr : TRY_CAST(CAST(0.999_d128(3,3) AS Decimal(4, 3)) AS Decimal(4, 0) NULL) +optimized expr : 1_d128(4,0) +func ctx : (modified) +output type : Decimal(4, 0) NULL +output domain : {1..=1} +output : 1 + + +ast : TRY_CAST(0.001::DECIMAL(4,3) AS DECIMAL(4,1)) +raw expr : TRY_CAST(CAST(0.001 AS Decimal(4, 3)) AS Decimal(4, 1)) +checked expr : TRY_CAST(CAST(0.001_d128(3,3) AS Decimal(4, 3)) AS Decimal(4, 1) NULL) +optimized expr : 0.0_d128(4,1) +func ctx : (modified) +output type : Decimal(4, 1) NULL +output domain : {0.0..=0.0} +output : 0.0 + + +ast : TRY_CAST(c AS DECIMAL(8,0)) +raw expr : TRY_CAST(c::Decimal(8, 3) AS Decimal(8, 0)) +checked expr : TRY_CAST(c AS Decimal(8, 0) NULL) +func ctx : (modified) +evaluation: ++--------+---------------------+--------------------+ +| | c | Output | ++--------+---------------------+--------------------+ +| Type | Decimal(8, 3) | Decimal(8, 0) NULL | +| Domain | {-99.999..=123.456} | Unknown | +| Row 0 | 12.345 | 12 | +| Row 1 | 67.890 | 68 | +| Row 2 | -11.111 | -11 | +| Row 3 | 99.999 | 100 | +| Row 4 | 0.000 | 0 | +| Row 5 | -99.999 | -100 | +| Row 6 | 123.456 | 123 | ++--------+---------------------+--------------------+ +evaluation (internal): ++--------+-------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | NullableColumn { column: Decimal128([12, 68, -11, 100, 0, -100, 123]), validity: [0b_1111111] } | ++--------+-------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(c AS DECIMAL(8,1)) +raw expr : TRY_CAST(c::Decimal(8, 3) AS Decimal(8, 1)) +checked expr : TRY_CAST(c AS Decimal(8, 1) NULL) +func ctx : (modified) +evaluation: ++--------+---------------------+--------------------+ +| | c | Output | ++--------+---------------------+--------------------+ +| Type | Decimal(8, 3) | Decimal(8, 1) NULL | +| Domain | {-99.999..=123.456} | Unknown | +| Row 0 | 12.345 | 12.3 | +| Row 1 | 67.890 | 67.9 | +| Row 2 | -11.111 | -11.1 | +| Row 3 | 99.999 | 100.0 | +| Row 4 | 0.000 | 0.0 | +| Row 5 | -99.999 | -100.0 | +| Row 6 | 123.456 | 123.5 | ++--------+---------------------+--------------------+ +evaluation (internal): ++--------+---------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+---------------------------------------------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | NullableColumn { column: Decimal128([12.3, 67.9, -11.1, 100.0, 0.0, -100.0, 123.5]), validity: [0b_1111111] } | ++--------+---------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(c AS DECIMAL(8,2)) +raw expr : TRY_CAST(c::Decimal(8, 3) AS Decimal(8, 2)) +checked expr : TRY_CAST(c AS Decimal(8, 2) NULL) +func ctx : (modified) +evaluation: ++--------+---------------------+--------------------+ +| | c | Output | ++--------+---------------------+--------------------+ +| Type | Decimal(8, 3) | Decimal(8, 2) NULL | +| Domain | {-99.999..=123.456} | Unknown | +| Row 0 | 12.345 | 12.35 | +| Row 1 | 67.890 | 67.89 | +| Row 2 | -11.111 | -11.11 | +| Row 3 | 99.999 | 100.00 | +| Row 4 | 0.000 | 0.00 | +| Row 5 | -99.999 | -100.00 | +| Row 6 | 123.456 | 123.46 | ++--------+---------------------+--------------------+ +evaluation (internal): ++--------+----------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+----------------------------------------------------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | NullableColumn { column: Decimal128([12.35, 67.89, -11.11, 100.00, 0.00, -100.00, 123.46]), validity: [0b_1111111] } | ++--------+----------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(123.456::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : TRY_CAST(CAST(123.456 AS Decimal(6, 3)) AS Decimal(6, 1)) +checked expr : TRY_CAST(123.456_d128(6,3) AS Decimal(6, 1) NULL) +optimized expr : 123.4_d128(6,1) +output type : Decimal(6, 1) NULL +output domain : {123.4..=123.4} +output : 123.4 + + +ast : TRY_CAST(123.999::DECIMAL(6,3) AS DECIMAL(6,2)) +raw expr : TRY_CAST(CAST(123.999 AS Decimal(6, 3)) AS Decimal(6, 2)) +checked expr : TRY_CAST(123.999_d128(6,3) AS Decimal(6, 2) NULL) +optimized expr : 123.99_d128(6,2) +output type : Decimal(6, 2) NULL +output domain : {123.99..=123.99} +output : 123.99 + + +ast : TRY_CAST(999.995::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : TRY_CAST(CAST(999.995 AS Decimal(6, 3)) AS Decimal(6, 1)) +checked expr : TRY_CAST(999.995_d128(6,3) AS Decimal(6, 1) NULL) +optimized expr : 999.9_d128(6,1) +output type : Decimal(6, 1) NULL +output domain : {999.9..=999.9} +output : 999.9 + + +ast : TRY_CAST(12.345::DECIMAL(5,3) AS DECIMAL(5,0)) +raw expr : TRY_CAST(CAST(12.345 AS Decimal(5, 3)) AS Decimal(5, 0)) +checked expr : TRY_CAST(12.345_d128(5,3) AS Decimal(5, 0) NULL) +optimized expr : 12_d128(5,0) +output type : Decimal(5, 0) NULL +output domain : {12..=12} +output : 12 + + +ast : TRY_CAST(12.567::DECIMAL(5,3) AS DECIMAL(5,1)) +raw expr : TRY_CAST(CAST(12.567 AS Decimal(5, 3)) AS Decimal(5, 1)) +checked expr : TRY_CAST(12.567_d128(5,3) AS Decimal(5, 1) NULL) +optimized expr : 12.5_d128(5,1) +output type : Decimal(5, 1) NULL +output domain : {12.5..=12.5} +output : 12.5 + + +ast : TRY_CAST(-12.345::DECIMAL(6,3) AS DECIMAL(6,1)) +raw expr : TRY_CAST(minus(CAST(12.345 AS Decimal(6, 3))) AS Decimal(6, 1)) +checked expr : TRY_CAST(minus(CAST(12.345_d128(5,3) AS Decimal(6, 3))) AS Decimal(6, 1) NULL) +optimized expr : -12.3_d128(6,1) +output type : Decimal(6, 1) NULL +output domain : {-12.3..=-12.3} +output : -12.3 + + +ast : TRY_CAST(-12.567::DECIMAL(6,3) AS DECIMAL(6,2)) +raw expr : TRY_CAST(minus(CAST(12.567 AS Decimal(6, 3))) AS Decimal(6, 2)) +checked expr : TRY_CAST(minus(CAST(12.567_d128(5,3) AS Decimal(6, 3))) AS Decimal(6, 2) NULL) +optimized expr : -12.56_d128(6,2) +output type : Decimal(6, 2) NULL +output domain : {-12.56..=-12.56} +output : -12.56 + + +ast : TRY_CAST(0.999::DECIMAL(4,3) AS DECIMAL(4,0)) +raw expr : TRY_CAST(CAST(0.999 AS Decimal(4, 3)) AS Decimal(4, 0)) +checked expr : TRY_CAST(CAST(0.999_d128(3,3) AS Decimal(4, 3)) AS Decimal(4, 0) NULL) +optimized expr : 0_d128(4,0) +output type : Decimal(4, 0) NULL +output domain : {0..=0} +output : 0 + + +ast : TRY_CAST(0.001::DECIMAL(4,3) AS DECIMAL(4,1)) +raw expr : TRY_CAST(CAST(0.001 AS Decimal(4, 3)) AS Decimal(4, 1)) +checked expr : TRY_CAST(CAST(0.001_d128(3,3) AS Decimal(4, 3)) AS Decimal(4, 1) NULL) +optimized expr : 0.0_d128(4,1) +output type : Decimal(4, 1) NULL +output domain : {0.0..=0.0} +output : 0.0 + + +ast : TRY_CAST(c AS DECIMAL(8,0)) +raw expr : TRY_CAST(c::Decimal(8, 3) AS Decimal(8, 0)) +checked expr : TRY_CAST(c AS Decimal(8, 0) NULL) +evaluation: ++--------+---------------------+--------------------+ +| | c | Output | ++--------+---------------------+--------------------+ +| Type | Decimal(8, 3) | Decimal(8, 0) NULL | +| Domain | {-99.999..=123.456} | Unknown | +| Row 0 | 12.345 | 12 | +| Row 1 | 67.890 | 67 | +| Row 2 | -11.111 | -11 | +| Row 3 | 99.999 | 99 | +| Row 4 | 0.000 | 0 | +| Row 5 | -99.999 | -99 | +| Row 6 | 123.456 | 123 | ++--------+---------------------+--------------------+ +evaluation (internal): ++--------+-----------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-----------------------------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | NullableColumn { column: Decimal128([12, 67, -11, 99, 0, -99, 123]), validity: [0b_1111111] } | ++--------+-----------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(c AS DECIMAL(8,1)) +raw expr : TRY_CAST(c::Decimal(8, 3) AS Decimal(8, 1)) +checked expr : TRY_CAST(c AS Decimal(8, 1) NULL) +evaluation: ++--------+---------------------+--------------------+ +| | c | Output | ++--------+---------------------+--------------------+ +| Type | Decimal(8, 3) | Decimal(8, 1) NULL | +| Domain | {-99.999..=123.456} | Unknown | +| Row 0 | 12.345 | 12.3 | +| Row 1 | 67.890 | 67.8 | +| Row 2 | -11.111 | -11.1 | +| Row 3 | 99.999 | 99.9 | +| Row 4 | 0.000 | 0.0 | +| Row 5 | -99.999 | -99.9 | +| Row 6 | 123.456 | 123.4 | ++--------+---------------------+--------------------+ +evaluation (internal): ++--------+-------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | NullableColumn { column: Decimal128([12.3, 67.8, -11.1, 99.9, 0.0, -99.9, 123.4]), validity: [0b_1111111] } | ++--------+-------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(c AS DECIMAL(8,2)) +raw expr : TRY_CAST(c::Decimal(8, 3) AS Decimal(8, 2)) +checked expr : TRY_CAST(c AS Decimal(8, 2) NULL) +evaluation: ++--------+---------------------+--------------------+ +| | c | Output | ++--------+---------------------+--------------------+ +| Type | Decimal(8, 3) | Decimal(8, 2) NULL | +| Domain | {-99.999..=123.456} | Unknown | +| Row 0 | 12.345 | 12.34 | +| Row 1 | 67.890 | 67.89 | +| Row 2 | -11.111 | -11.11 | +| Row 3 | 99.999 | 99.99 | +| Row 4 | 0.000 | 0.00 | +| Row 5 | -99.999 | -99.99 | +| Row 6 | 123.456 | 123.45 | ++--------+---------------------+--------------------+ +evaluation (internal): ++--------+--------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+--------------------------------------------------------------------------------------------------------------------+ +| c | Decimal128([12.345, 67.890, -11.111, 99.999, 0.000, -99.999, 123.456]) | +| Output | NullableColumn { column: Decimal128([12.34, 67.89, -11.11, 99.99, 0.00, -99.99, 123.45]), validity: [0b_1111111] } | ++--------+--------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(12345.67::DECIMAL(7,2) AS DECIMAL(5,2)) +raw expr : TRY_CAST(CAST(12345.67 AS Decimal(7, 2)) AS Decimal(5, 2)) +checked expr : TRY_CAST(12345.67_d128(7,2) AS Decimal(5, 2) NULL) +optimized expr : NULL +output type : Decimal(5, 2) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(999.99::DECIMAL(5,2) AS DECIMAL(4,2)) +raw expr : TRY_CAST(CAST(999.99 AS Decimal(5, 2)) AS Decimal(4, 2)) +checked expr : TRY_CAST(999.99_d128(5,2) AS Decimal(4, 2) NULL) +optimized expr : NULL +output type : Decimal(4, 2) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(99.9::DECIMAL(3,1) AS DECIMAL(2,1)) +raw expr : TRY_CAST(CAST(99.9 AS Decimal(3, 1)) AS Decimal(2, 1)) +checked expr : TRY_CAST(99.9_d128(3,1) AS Decimal(2, 1) NULL) +optimized expr : NULL +output type : Decimal(2, 1) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(-999.999::DECIMAL(6,3) AS DECIMAL(4,1)) +raw expr : TRY_CAST(minus(CAST(999.999 AS Decimal(6, 3))) AS Decimal(4, 1)) +checked expr : TRY_CAST(minus(999.999_d128(6,3)) AS Decimal(4, 1) NULL) +optimized expr : -999.9_d128(4,1) +output type : Decimal(4, 1) NULL +output domain : {-999.9..=-999.9} +output : -999.9 + + +ast : TRY_CAST(-123.45::DECIMAL(5,2) AS DECIMAL(4,2)) +raw expr : TRY_CAST(minus(CAST(123.45 AS Decimal(5, 2))) AS Decimal(4, 2)) +checked expr : TRY_CAST(minus(123.45_d128(5,2)) AS Decimal(4, 2) NULL) +optimized expr : NULL +output type : Decimal(4, 2) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(99.99::DECIMAL(4,2) AS DECIMAL(3,2)) +raw expr : TRY_CAST(CAST(99.99 AS Decimal(4, 2)) AS Decimal(3, 2)) +checked expr : TRY_CAST(99.99_d128(4,2) AS Decimal(3, 2) NULL) +optimized expr : NULL +output type : Decimal(3, 2) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(9.99::DECIMAL(3,2) AS DECIMAL(2,2)) +raw expr : TRY_CAST(CAST(9.99 AS Decimal(3, 2)) AS Decimal(2, 2)) +checked expr : TRY_CAST(9.99_d128(3,2) AS Decimal(2, 2) NULL) +optimized expr : NULL +output type : Decimal(2, 2) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(123.45::DECIMAL(5,2) AS DECIMAL(38,10)) +raw expr : TRY_CAST(CAST(123.45 AS Decimal(5, 2)) AS Decimal(38, 10)) +checked expr : TRY_CAST(123.45_d128(5,2) AS Decimal(38, 10) NULL) +optimized expr : 123.4500000000_d128(38,10) +output type : Decimal(38, 10) NULL +output domain : {123.4500000000..=123.4500000000} +output : 123.4500000000 + + +ast : TRY_CAST(123456789.123456789::DECIMAL(18,9) AS DECIMAL(38,20)) +raw expr : TRY_CAST(CAST(123456789.123456789 AS Decimal(18, 9)) AS Decimal(38, 20)) +checked expr : TRY_CAST(123456789.123456789_d128(18,9) AS Decimal(38, 20) NULL) +optimized expr : 123456789.12345678900000000000_d128(38,20) +output type : Decimal(38, 20) NULL +output domain : {123456789.12345678900000000000..=123456789.12345678900000000000} +output : 123456789.12345678900000000000 + + +ast : TRY_CAST(12345678901234567890.123456789::DECIMAL(38,9) AS DECIMAL(18,4)) +raw expr : TRY_CAST(CAST(12345678901234567890.123456789 AS Decimal(38, 9)) AS Decimal(18, 4)) +checked expr : TRY_CAST(CAST(12345678901234567890.123456789_d128(29,9) AS Decimal(38, 9)) AS Decimal(18, 4) NULL) +optimized expr : NULL +output type : Decimal(18, 4) NULL +output domain : {NULL} +output : NULL + + +ast : TRY_CAST(99.99::DECIMAL(4,2) AS DECIMAL(6,2)) +raw expr : TRY_CAST(CAST(99.99 AS Decimal(4, 2)) AS Decimal(6, 2)) +checked expr : TRY_CAST(99.99_d128(4,2) AS Decimal(6, 2) NULL) +optimized expr : 99.99_d128(6,2) +output type : Decimal(6, 2) NULL +output domain : {99.99..=99.99} +output : 99.99 + + +ast : TRY_CAST(999999.999::DECIMAL(9,3) AS DECIMAL(15,6)) +raw expr : TRY_CAST(CAST(999999.999 AS Decimal(9, 3)) AS Decimal(15, 6)) +checked expr : TRY_CAST(999999.999_d128(9,3) AS Decimal(15, 6) NULL) +optimized expr : 999999.999000_d128(15,6) +output type : Decimal(15, 6) NULL +output domain : {999999.999000..=999999.999000} +output : 999999.999000 + + +ast : TRY_CAST(a AS DECIMAL(15,3)) +raw expr : TRY_CAST(a::Decimal(10, 2) AS Decimal(15, 3)) +checked expr : TRY_CAST(a AS Decimal(15, 3) NULL) +evaluation: ++--------+----------------------------+---------------------+ +| | a | Output | ++--------+----------------------------+---------------------+ +| Type | Decimal(10, 2) | Decimal(15, 3) NULL | +| Domain | {-9876543.21..=1234567.89} | Unknown | +| Row 0 | 0.00 | 0.000 | +| Row 1 | 0.01 | 0.010 | +| Row 2 | -0.01 | -0.010 | +| Row 3 | 1234567.89 | 1234567.890 | +| Row 4 | -9876543.21 | -9876543.210 | +| Row 5 | 9999.99 | 9999.990 | ++--------+----------------------------+---------------------+ +evaluation (internal): ++--------+----------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+----------------------------------------------------------------------------------------------------------------------------+ +| a | Decimal128([0.00, 0.01, -0.01, 1234567.89, -9876543.21, 9999.99]) | +| Output | NullableColumn { column: Decimal128([0.000, 0.010, -0.010, 1234567.890, -9876543.210, 9999.990]), validity: [0b__111111] } | ++--------+----------------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(a AS DECIMAL(20,5)) +raw expr : TRY_CAST(a::Decimal(10, 2) AS Decimal(20, 5)) +checked expr : TRY_CAST(a AS Decimal(20, 5) NULL) +evaluation: ++--------+----------------------------+---------------------+ +| | a | Output | ++--------+----------------------------+---------------------+ +| Type | Decimal(10, 2) | Decimal(20, 5) NULL | +| Domain | {-9876543.21..=1234567.89} | Unknown | +| Row 0 | 0.00 | 0.00000 | +| Row 1 | 0.01 | 0.01000 | +| Row 2 | -0.01 | -0.01000 | +| Row 3 | 1234567.89 | 1234567.89000 | +| Row 4 | -9876543.21 | -9876543.21000 | +| Row 5 | 9999.99 | 9999.99000 | ++--------+----------------------------+---------------------+ +evaluation (internal): ++--------+----------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+----------------------------------------------------------------------------------------------------------------------------------------+ +| a | Decimal128([0.00, 0.01, -0.01, 1234567.89, -9876543.21, 9999.99]) | +| Output | NullableColumn { column: Decimal128([0.00000, 0.01000, -0.01000, 1234567.89000, -9876543.21000, 9999.99000]), validity: [0b__111111] } | ++--------+----------------------------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(b AS DECIMAL(10,2)) +raw expr : TRY_CAST(b::Decimal(15, 3) AS Decimal(10, 2)) +checked expr : TRY_CAST(b AS Decimal(10, 2) NULL) +evaluation: ++--------+----------------------------+---------------------+ +| | b | Output | ++--------+----------------------------+---------------------+ +| Type | Decimal(15, 3) | Decimal(10, 2) NULL | +| Domain | {-987654.320..=123456.780} | Unknown | +| Row 0 | 0.000 | 0.00 | +| Row 1 | 0.002 | 0.00 | +| Row 2 | -0.002 | 0.00 | +| Row 3 | 123456.780 | 123456.78 | +| Row 4 | -987654.320 | -987654.32 | +| Row 5 | 1000.000 | 1000.00 | ++--------+----------------------------+---------------------+ +evaluation (internal): ++--------+-------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------------------------------------------------+ +| b | Decimal256([0.000, 0.002, -0.002, 123456.780, -987654.320, 1000.000]) | +| Output | NullableColumn { column: Decimal128([0.00, 0.00, 0.00, 123456.78, -987654.32, 1000.00]), validity: [0b__111111] } | ++--------+-------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(b AS DECIMAL(38,10)) +raw expr : TRY_CAST(b::Decimal(15, 3) AS Decimal(38, 10)) +checked expr : TRY_CAST(b AS Decimal(38, 10) NULL) +evaluation: ++--------+----------------------------+----------------------+ +| | b | Output | ++--------+----------------------------+----------------------+ +| Type | Decimal(15, 3) | Decimal(38, 10) NULL | +| Domain | {-987654.320..=123456.780} | Unknown | +| Row 0 | 0.000 | 0.0000000000 | +| Row 1 | 0.002 | 0.0020000000 | +| Row 2 | -0.002 | -0.0020000000 | +| Row 3 | 123456.780 | 123456.7800000000 | +| Row 4 | -987654.320 | -987654.3200000000 | +| Row 5 | 1000.000 | 1000.0000000000 | ++--------+----------------------------+----------------------+ +evaluation (internal): ++--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| b | Decimal256([0.000, 0.002, -0.002, 123456.780, -987654.320, 1000.000]) | +| Output | NullableColumn { column: Decimal128([0.0000000000, 0.0020000000, -0.0020000000, 123456.7800000000, -987654.3200000000, 1000.0000000000]), validity: [0b__111111] } | ++--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(a AS DECIMAL(5,1)) +raw expr : TRY_CAST(a::Decimal(10, 2) AS Decimal(5, 1)) +checked expr : TRY_CAST(a AS Decimal(5, 1) NULL) +evaluation: ++--------+----------------------------+--------------------+ +| | a | Output | ++--------+----------------------------+--------------------+ +| Type | Decimal(10, 2) | Decimal(5, 1) NULL | +| Domain | {-9876543.21..=1234567.89} | Unknown | +| Row 0 | 0.00 | 0.0 | +| Row 1 | 0.01 | 0.0 | +| Row 2 | -0.01 | 0.0 | +| Row 3 | 1234567.89 | NULL | +| Row 4 | -9876543.21 | NULL | +| Row 5 | 9999.99 | 9999.9 | ++--------+----------------------------+--------------------+ +evaluation (internal): ++--------+--------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+--------------------------------------------------------------------------------------------------+ +| a | Decimal128([0.00, 0.01, -0.01, 1234567.89, -9876543.21, 9999.99]) | +| Output | NullableColumn { column: Decimal128([0.0, 0.0, 0.0, 0.1, 0.1, 9999.9]), validity: [0b__100111] } | ++--------+--------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(b AS DECIMAL(8,2)) +raw expr : TRY_CAST(b::Decimal(15, 3) AS Decimal(8, 2)) +checked expr : TRY_CAST(b AS Decimal(8, 2) NULL) +evaluation: ++--------+----------------------------+--------------------+ +| | b | Output | ++--------+----------------------------+--------------------+ +| Type | Decimal(15, 3) | Decimal(8, 2) NULL | +| Domain | {-987654.320..=123456.780} | Unknown | +| Row 0 | 0.000 | 0.00 | +| Row 1 | 0.002 | 0.00 | +| Row 2 | -0.002 | 0.00 | +| Row 3 | 123456.780 | 123456.78 | +| Row 4 | -987654.320 | -987654.32 | +| Row 5 | 1000.000 | 1000.00 | ++--------+----------------------------+--------------------+ +evaluation (internal): ++--------+-------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------------------------------------------------+ +| b | Decimal256([0.000, 0.002, -0.002, 123456.780, -987654.320, 1000.000]) | +| Output | NullableColumn { column: Decimal128([0.00, 0.00, 0.00, 123456.78, -987654.32, 1000.00]), validity: [0b__111111] } | ++--------+-------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(d AS DECIMAL(20,5)) +raw expr : TRY_CAST(d::Decimal(38, 10) AS Decimal(20, 5)) +checked expr : TRY_CAST(d AS Decimal(20, 5) NULL) +evaluation: ++--------+----------------------------------------------+---------------------+ +| | d | Output | ++--------+----------------------------------------------+---------------------+ +| Type | Decimal(38, 10) | Decimal(20, 5) NULL | +| Domain | {-99999999.9999999999..=99999999.9999999999} | Unknown | +| Row 0 | 99999999.9999999999 | 99999999.99999 | +| Row 1 | -99999999.9999999999 | -99999999.99999 | +| Row 2 | 0.0000000000 | 0.00000 | +| Row 3 | 12345.6789012345 | 12345.67890 | +| Row 4 | -12345.6789012345 | -12345.67890 | ++--------+----------------------------------------------+---------------------+ +evaluation (internal): ++--------+--------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+--------------------------------------------------------------------------------------------------------------------------------------+ +| d | Decimal256([99999999.9999999999, -99999999.9999999999, 0.0000000000, 12345.6789012345, -12345.6789012345]) | +| Output | NullableColumn { column: Decimal128([99999999.99999, -99999999.99999, 0.00000, 12345.67890, -12345.67890]), validity: [0b___11111] } | ++--------+--------------------------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(d AS DECIMAL(38,15)) +raw expr : TRY_CAST(d::Decimal(38, 10) AS Decimal(38, 15)) +checked expr : TRY_CAST(d AS Decimal(38, 15) NULL) +evaluation: ++--------+----------------------------------------------+---------------------------+ +| | d | Output | ++--------+----------------------------------------------+---------------------------+ +| Type | Decimal(38, 10) | Decimal(38, 15) NULL | +| Domain | {-99999999.9999999999..=99999999.9999999999} | Unknown | +| Row 0 | 99999999.9999999999 | 99999999.999999999900000 | +| Row 1 | -99999999.9999999999 | -99999999.999999999900000 | +| Row 2 | 0.0000000000 | 0.000000000000000 | +| Row 3 | 12345.6789012345 | 12345.678901234500000 | +| Row 4 | -12345.6789012345 | -12345.678901234500000 | ++--------+----------------------------------------------+---------------------------+ +evaluation (internal): ++--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| d | Decimal256([99999999.9999999999, -99999999.9999999999, 0.0000000000, 12345.6789012345, -12345.6789012345]) | +| Output | NullableColumn { column: Decimal128([99999999.999999999900000, -99999999.999999999900000, 0.000000000000000, 12345.678901234500000, -12345.678901234500000]), validity: [0b___11111] } | ++--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast : TRY_CAST(d AS DECIMAL(15,2)) +raw expr : TRY_CAST(d::Decimal(38, 10) AS Decimal(15, 2)) +checked expr : TRY_CAST(d AS Decimal(15, 2) NULL) +evaluation: ++--------+----------------------------------------------+---------------------+ +| | d | Output | ++--------+----------------------------------------------+---------------------+ +| Type | Decimal(38, 10) | Decimal(15, 2) NULL | +| Domain | {-99999999.9999999999..=99999999.9999999999} | Unknown | +| Row 0 | 99999999.9999999999 | 99999999.99 | +| Row 1 | -99999999.9999999999 | -99999999.99 | +| Row 2 | 0.0000000000 | 0.00 | +| Row 3 | 12345.6789012345 | 12345.67 | +| Row 4 | -12345.6789012345 | -12345.67 | ++--------+----------------------------------------------+---------------------+ +evaluation (internal): ++--------+-----------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-----------------------------------------------------------------------------------------------------------------------+ +| d | Decimal256([99999999.9999999999, -99999999.9999999999, 0.0000000000, 12345.6789012345, -12345.6789012345]) | +| Output | NullableColumn { column: Decimal128([99999999.99, -99999999.99, 0.00, 12345.67, -12345.67]), validity: [0b___11111] } | ++--------+-----------------------------------------------------------------------------------------------------------------------+ + + 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 5bf48cc295008..f83d6c14e23b1 100644 --- a/src/query/functions/tests/it/scalars/testdata/function_list.txt +++ b/src/query/functions/tests/it/scalars/testdata/function_list.txt @@ -2541,23 +2541,23 @@ Functions overloads: 1 minus(Variant NULL, Int32 NULL) :: Variant NULL 2 minus(Variant, String) :: Variant 3 minus(Variant NULL, String NULL) :: Variant NULL -4 minus(UInt8) :: Int16 -5 minus(UInt8 NULL) :: Int16 NULL -6 minus(Int8) :: Int16 -7 minus(Int8 NULL) :: Int16 NULL -8 minus(UInt16) :: Int32 -9 minus(UInt16 NULL) :: Int32 NULL -10 minus(Int16) :: Int32 -11 minus(Int16 NULL) :: Int32 NULL -12 minus(UInt32) :: Int64 -13 minus(UInt32 NULL) :: Int64 NULL -14 minus(Int32) :: Int64 -15 minus(Int32 NULL) :: Int64 NULL -16 minus(UInt64) :: Int64 -17 minus(UInt64 NULL) :: Int64 NULL -18 minus(Int64) :: Int64 -19 minus(Int64 NULL) :: Int64 NULL -20 minus FACTORY +4 minus FACTORY +5 minus(UInt8) :: Int16 +6 minus(UInt8 NULL) :: Int16 NULL +7 minus(Int8) :: Int16 +8 minus(Int8 NULL) :: Int16 NULL +9 minus(UInt16) :: Int32 +10 minus(UInt16 NULL) :: Int32 NULL +11 minus(Int16) :: Int32 +12 minus(Int16 NULL) :: Int32 NULL +13 minus(UInt32) :: Int64 +14 minus(UInt32 NULL) :: Int64 NULL +15 minus(Int32) :: Int64 +16 minus(Int32 NULL) :: Int64 NULL +17 minus(UInt64) :: Int64 +18 minus(UInt64 NULL) :: Int64 NULL +19 minus(Int64) :: Int64 +20 minus(Int64 NULL) :: Int64 NULL 21 minus(Float32) :: Float32 22 minus(Float32 NULL) :: Float32 NULL 23 minus(Float64) :: Float64 diff --git a/src/query/functions/tests/it/type_check.rs b/src/query/functions/tests/it/type_check.rs index bbc02d0ca828c..e9f7ef51ee11f 100644 --- a/src/query/functions/tests/it/type_check.rs +++ b/src/query/functions/tests/it/type_check.rs @@ -70,15 +70,21 @@ fn test_type_check() { "n_j", VariantType::from_data(vec![json.clone()]).wrap_nullable(None), ), - ("d128", Decimal128Type::from_data(vec![0_i128])), + ( + "d128", + Decimal128Type::from_data_with_size(vec![0_i128], None), + ), ( "n_d128", - Decimal128Type::from_data(vec![0_i128]).wrap_nullable(None), + Decimal128Type::from_opt_data_with_size(vec![Some(0_i128)], None), + ), + ( + "d256", + Decimal256Type::from_data_with_size(vec![i256::ZERO], None), ), - ("d256", Decimal256Type::from_data(vec![i256::ZERO])), ( "n_d256", - Decimal256Type::from_data(vec![i256::ZERO]).wrap_nullable(None), + Decimal256Type::from_opt_data_with_size(vec![Some(i256::ZERO)], None), ), ]; diff --git a/src/query/service/src/pipelines/processors/transforms/aggregator/serde/transform_exchange_aggregate_serializer.rs b/src/query/service/src/pipelines/processors/transforms/aggregator/serde/transform_exchange_aggregate_serializer.rs index e533b8f20b281..b71edc2033bdc 100644 --- a/src/query/service/src/pipelines/processors/transforms/aggregator/serde/transform_exchange_aggregate_serializer.rs +++ b/src/query/service/src/pipelines/processors/transforms/aggregator/serde/transform_exchange_aggregate_serializer.rs @@ -23,11 +23,11 @@ use databend_common_base::runtime::profile::ProfileStatisticsName; use databend_common_catalog::table_context::TableContext; use databend_common_exception::Result; use databend_common_expression::arrow::serialize_column; -use databend_common_expression::types::AccessType; use databend_common_expression::types::ArrayType; use databend_common_expression::types::Int64Type; use databend_common_expression::types::ReturnType; use databend_common_expression::types::UInt64Type; +use databend_common_expression::types::ValueType; use databend_common_expression::BlockMetaInfoDowncast; use databend_common_expression::DataBlock; use databend_common_expression::DataSchemaRef; diff --git a/src/query/service/src/table_functions/cloud/task_dependents.rs b/src/query/service/src/table_functions/cloud/task_dependents.rs index bce45caa2b44c..69192625e5f67 100644 --- a/src/query/service/src/table_functions/cloud/task_dependents.rs +++ b/src/query/service/src/table_functions/cloud/task_dependents.rs @@ -32,11 +32,11 @@ use databend_common_cloud_control::pb::Task; use databend_common_cloud_control::task_utils; use databend_common_config::GlobalConfig; use databend_common_exception::ErrorCode; -use databend_common_expression::types::AccessType; use databend_common_expression::types::ArrayType; use databend_common_expression::types::ReturnType; use databend_common_expression::types::StringType; use databend_common_expression::types::TimestampType; +use databend_common_expression::types::ValueType; use databend_common_expression::DataBlock; use databend_common_expression::FromData; use databend_common_expression::TableDataType; diff --git a/src/query/service/src/table_functions/inspect_parquet/inspect_parquet_table.rs b/src/query/service/src/table_functions/inspect_parquet/inspect_parquet_table.rs index 8c887a967d573..e483df46c8a7f 100644 --- a/src/query/service/src/table_functions/inspect_parquet/inspect_parquet_table.rs +++ b/src/query/service/src/table_functions/inspect_parquet/inspect_parquet_table.rs @@ -24,12 +24,12 @@ use databend_common_catalog::table::Table; use databend_common_catalog::table_args::TableArgs; use databend_common_exception::ErrorCode; use databend_common_exception::Result; -use databend_common_expression::types::AccessType; use databend_common_expression::types::DataType; use databend_common_expression::types::Int64Type; use databend_common_expression::types::NumberDataType; use databend_common_expression::types::StringType; use databend_common_expression::types::UInt64Type; +use databend_common_expression::types::ValueType; use databend_common_expression::BlockEntry; use databend_common_expression::DataBlock; use databend_common_expression::TableDataType; diff --git a/src/query/service/src/table_functions/others/tenant_quota.rs b/src/query/service/src/table_functions/others/tenant_quota.rs index eb05b905b8524..b368abccf3c8d 100644 --- a/src/query/service/src/table_functions/others/tenant_quota.rs +++ b/src/query/service/src/table_functions/others/tenant_quota.rs @@ -25,10 +25,10 @@ use databend_common_catalog::table_context::TableContext; use databend_common_catalog::table_function::TableFunction; use databend_common_exception::ErrorCode; use databend_common_exception::Result; -use databend_common_expression::types::AccessType; use databend_common_expression::types::DataType; use databend_common_expression::types::NumberDataType; use databend_common_expression::types::UInt32Type; +use databend_common_expression::types::ValueType; use databend_common_expression::BlockEntry; use databend_common_expression::DataBlock; use databend_common_expression::Scalar; diff --git a/src/query/sql/src/planner/semantic/type_check.rs b/src/query/sql/src/planner/semantic/type_check.rs index f3ab76676e29f..a56cd46b5a995 100644 --- a/src/query/sql/src/planner/semantic/type_check.rs +++ b/src/query/sql/src/planner/semantic/type_check.rs @@ -66,7 +66,6 @@ use databend_common_expression::infer_schema_type; use databend_common_expression::shrink_scalar; use databend_common_expression::type_check; use databend_common_expression::type_check::check_number; -use databend_common_expression::types::decimal::DecimalDataType; use databend_common_expression::types::decimal::DecimalScalar; use databend_common_expression::types::decimal::DecimalSize; use databend_common_expression::types::decimal::MAX_DECIMAL128_PRECISION; @@ -5733,9 +5732,9 @@ pub fn resolve_type_name(type_name: &TypeName, not_null: bool) -> Result TableDataType::Number(NumberDataType::Int64), TypeName::Float32 => TableDataType::Number(NumberDataType::Float32), TypeName::Float64 => TableDataType::Number(NumberDataType::Float64), - TypeName::Decimal { precision, scale } => TableDataType::Decimal( - DecimalDataType::from_size(DecimalSize::new_unchecked(*precision, *scale))?, - ), + TypeName::Decimal { precision, scale } => { + TableDataType::Decimal(DecimalSize::new(*precision, *scale)?.into()) + } TypeName::Binary => TableDataType::Binary, TypeName::String => TableDataType::String, TypeName::Timestamp => TableDataType::Timestamp, diff --git a/src/query/storages/common/index/src/range_index.rs b/src/query/storages/common/index/src/range_index.rs index 2662c100c2b69..e1b1e0b02d533 100644 --- a/src/query/storages/common/index/src/range_index.rs +++ b/src/query/storages/common/index/src/range_index.rs @@ -27,9 +27,12 @@ use databend_common_expression::types::string::StringDomain; use databend_common_expression::types::AccessType; use databend_common_expression::types::DataType; use databend_common_expression::types::DateType; +use databend_common_expression::types::Decimal64Type; +use databend_common_expression::types::DecimalScalar; use databend_common_expression::types::NumberDataType; use databend_common_expression::types::NumberType; use databend_common_expression::types::TimestampType; +use databend_common_expression::types::ValueType; use databend_common_expression::visit_expr; use databend_common_expression::with_number_mapped_type; use databend_common_expression::ColumnId; @@ -241,23 +244,33 @@ pub fn statistics_to_domain(mut stats: Vec<&ColumnStatistics>, data_type: &DataT max: DateType::try_downcast_scalar(&max.as_ref()).unwrap(), }), DataType::Decimal(size) => { - if min.as_decimal().unwrap().is_decimal128() { - Domain::Decimal(DecimalDomain::Decimal128( - SimpleDomain { + debug_assert_eq!(*size, min.as_decimal().unwrap().size()); + debug_assert_eq!(*size, max.as_decimal().unwrap().size()); + + let domain = match min.as_decimal().unwrap() { + DecimalScalar::Decimal64(_, _) => { + let domain = SimpleDomain { + min: Decimal64Type::try_downcast_scalar(&min.as_ref()).unwrap(), + max: Decimal64Type::try_downcast_scalar(&max.as_ref()).unwrap(), + }; + DecimalDomain::Decimal64(domain, *size) + } + DecimalScalar::Decimal128(_, _) => { + let domain = SimpleDomain { min: Decimal128Type::try_downcast_scalar(&min.as_ref()).unwrap(), max: Decimal128Type::try_downcast_scalar(&max.as_ref()).unwrap(), - }, - *size, - )) - } else { - Domain::Decimal(DecimalDomain::Decimal256( - SimpleDomain { + }; + DecimalDomain::Decimal128(domain, *size) + } + DecimalScalar::Decimal256(_, _) => { + let domain = SimpleDomain { min: Decimal256Type::try_downcast_scalar(&min.as_ref()).unwrap(), max: Decimal256Type::try_downcast_scalar(&max.as_ref()).unwrap(), - }, - *size, - )) - } + }; + DecimalDomain::Decimal256(domain, *size) + } + }; + Domain::Decimal(domain) } // Unsupported data type diff --git a/src/query/storages/common/table_meta/src/meta/v2/statistics.rs b/src/query/storages/common/table_meta/src/meta/v2/statistics.rs index da9d5f3d9c158..1a700bf2e5954 100644 --- a/src/query/storages/common/table_meta/src/meta/v2/statistics.rs +++ b/src/query/storages/common/table_meta/src/meta/v2/statistics.rs @@ -96,7 +96,10 @@ impl ColumnStatistics { in_memory_size: u64, distinct_of_values: Option, ) -> Self { - assert!(min.as_ref().infer_common_type(&max.as_ref()).is_some()); + assert!( + min.as_ref().infer_common_type(&max.as_ref()).is_some(), + "must have same type, min: {min}, max: {max}", + ); Self { min, diff --git a/src/query/storages/fuse/src/operations/changes.rs b/src/query/storages/fuse/src/operations/changes.rs index 49431a507c471..b8e72be455d15 100644 --- a/src/query/storages/fuse/src/operations/changes.rs +++ b/src/query/storages/fuse/src/operations/changes.rs @@ -32,7 +32,6 @@ use databend_common_catalog::table_context::TableContext; use databend_common_exception::ErrorCode; use databend_common_exception::Result; use databend_common_expression::types::decimal::Decimal128Type; -use databend_common_expression::FromData; use databend_common_expression::RemoteExpr; use databend_common_expression::Scalar; use databend_common_expression::BASE_BLOCK_IDS_COL_NAME; @@ -274,7 +273,7 @@ impl FuseTable { base_block_ids.push(block_id); } let base_block_ids_scalar = - Scalar::Array(Decimal128Type::from_data(base_block_ids)); + Scalar::Array(Decimal128Type::from_data_with_size(base_block_ids, None)); push_downs = replace_push_downs(push_downs, &base_block_ids_scalar)?; (add_blocks, Some(base_block_ids_scalar)) } diff --git a/src/query/storages/fuse/src/operations/replace_into/mutator/column_hash.rs b/src/query/storages/fuse/src/operations/replace_into/mutator/column_hash.rs index e26e97c9eefe7..8275f1c21df00 100644 --- a/src/query/storages/fuse/src/operations/replace_into/mutator/column_hash.rs +++ b/src/query/storages/fuse/src/operations/replace_into/mutator/column_hash.rs @@ -72,6 +72,9 @@ pub fn row_hash_of_columns( ScalarRef::String(v) => sip.write(v.as_bytes()), ScalarRef::Bitmap(v) => sip.write(v), ScalarRef::Decimal(v) => match v { + DecimalScalar::Decimal64(_, _) => { + unreachable!() + } DecimalScalar::Decimal128(i, size) => { sip.write_i128(i); sip.write_u8(size.precision()); diff --git a/src/query/storages/iceberg/src/statistics.rs b/src/query/storages/iceberg/src/statistics.rs index 17cb648cd5e36..2de527d9475ca 100644 --- a/src/query/storages/iceberg/src/statistics.rs +++ b/src/query/storages/iceberg/src/statistics.rs @@ -22,7 +22,9 @@ use databend_common_exception::ErrorCode; use databend_common_exception::Result; use databend_common_expression::types::Decimal; use databend_common_expression::types::DecimalSize; +use databend_common_expression::types::Int64Type; use databend_common_expression::types::Number; +use databend_common_expression::types::ValueType; use databend_common_expression::types::F32; use databend_common_expression::types::F64; use databend_common_expression::ColumnId; @@ -222,7 +224,7 @@ pub fn parse_datum(data: &Datum) -> Option { match data.literal() { PrimitiveLiteral::Boolean(v) => Some(Scalar::Boolean(*v)), PrimitiveLiteral::Int(v) => Some(Scalar::Number(i32::upcast_scalar(*v))), - PrimitiveLiteral::Long(v) => Some(Scalar::Number(i64::upcast_scalar(*v))), + PrimitiveLiteral::Long(v) => Some(Int64Type::upcast_scalar(*v)), PrimitiveLiteral::Float(v) => { Some(Scalar::Number(F32::upcast_scalar(OrderedFloat::from(v.0)))) } diff --git a/src/query/storages/stage/src/read/avro/avro_to_jsonb.rs b/src/query/storages/stage/src/read/avro/avro_to_jsonb.rs index 6a204fc6a1183..1423f93e3969b 100644 --- a/src/query/storages/stage/src/read/avro/avro_to_jsonb.rs +++ b/src/query/storages/stage/src/read/avro/avro_to_jsonb.rs @@ -186,7 +186,7 @@ mod tests { let cases = vec![ (7, 4, 1234567i128, 7), (7, 4, 123456i128, 6), - (38, 10, i128::MAX, 38), + (38, 10, i128::DECIMAL_MAX, 38), ]; for (p, s, v, digits) in cases { let (value, schema) = create_avro_decimal(&v.to_string(), p, s); @@ -224,7 +224,7 @@ mod tests { i256::from_i128(i128::MAX).mul(i256::from_i128(10)), 39, ), - (72, 10, i256::MAX, 72), + (72, 10, i256::DECIMAL_MAX, 72), ]; for (p, s, v, digits) in cases { let (value, schema) = create_avro_decimal(&v.to_string(), p, s); diff --git a/src/query/storages/stage/src/read/avro/decoder.rs b/src/query/storages/stage/src/read/avro/decoder.rs index 9f52b87c49d60..bccede4b2ade4 100644 --- a/src/query/storages/stage/src/read/avro/decoder.rs +++ b/src/query/storages/stage/src/read/avro/decoder.rs @@ -231,7 +231,7 @@ impl AvroDecoder { fn read_field( &self, - column: &mut ColumnBuilder, + builder: &mut ColumnBuilder, value: Value, matched_schema: &MatchedSchema, ) -> ReadFieldResult { @@ -249,7 +249,7 @@ impl AvroDecoder { (matched_schema, value) }; - match column { + match builder { ColumnBuilder::Nullable(c) => self.read_nullable(c, value, matched_schema), ColumnBuilder::Null { len } => self.read_null(len, value), ColumnBuilder::Boolean(c) => self.read_bool(c, value), @@ -291,7 +291,7 @@ impl AvroDecoder { // todo: Bitmap, Geometry, Geography _ => Err(Error::new_reason(format!( "loading avro to table with column of type {} not supported yet", - column.data_type() + builder.data_type() ))), } } @@ -411,7 +411,7 @@ impl AvroDecoder { let scale_diff = (size.scale() as i64) - v_scale; if scale_diff > 0 { d1 = d1 - .checked_mul(D::e(scale_diff as u32)) + .checked_mul(D::e(scale_diff as u8)) .expect("rescale should not overflow"); } column.push(d1); diff --git a/src/query/storages/stage/src/read/avro/schema_match.rs b/src/query/storages/stage/src/read/avro/schema_match.rs index 1cfefcb1c7472..be45c56a7b2fc 100644 --- a/src/query/storages/stage/src/read/avro/schema_match.rs +++ b/src/query/storages/stage/src/read/avro/schema_match.rs @@ -103,12 +103,8 @@ impl SchemaMatcher { if (d1.leading_digits() as usize) >= d2.precision - d2.scale && (d1.scale() as usize) >= d2.scale => { - let diff = (d1.scale() as usize) - d2.scale; - let multiplier = if diff > 0 { - Some(i256::e(diff as u32)) - } else { - None - }; + let diff = d1.scale() - d2.scale as u8; + let multiplier = if diff > 0 { Some(i256::e(diff)) } else { None }; Ok(MatchedSchema::Decimal { multiplier }) } (TableDataType::Number(NumberDataType::Int32), Schema::Int) diff --git a/src/query/storages/system/src/malloc_stats_totals_table.rs b/src/query/storages/system/src/malloc_stats_totals_table.rs index 5b3ae5df63cf1..9fa57054fb59d 100644 --- a/src/query/storages/system/src/malloc_stats_totals_table.rs +++ b/src/query/storages/system/src/malloc_stats_totals_table.rs @@ -21,10 +21,10 @@ use databend_common_catalog::table_context::TableContext; use databend_common_exception::ErrorCode; use databend_common_exception::Result; use databend_common_expression::types::string::StringColumnBuilder; -use databend_common_expression::types::AccessType; use databend_common_expression::types::NumberDataType; use databend_common_expression::types::NumberType; use databend_common_expression::types::StringType; +use databend_common_expression::types::ValueType; use databend_common_expression::Column; use databend_common_expression::DataBlock; use databend_common_expression::TableDataType;