Skip to content

Commit

Permalink
feat: impl Vector, DataType traits for decimal128 (#2727)
Browse files Browse the repository at this point in the history
* feat: decimal128 vector

* feat: Decimal128Type in datatypes

* refactor: cast function

* feat: decimal128 type in ConcreteDataType

* chore: decimal

* chore: sql_data_type_to_concrete_data_type

* chore: cr comment

Co-authored-by: Dennis Zhuang <[email protected]>
Co-authored-by: Yingwen <[email protected]>

* chore: fix finish()

* chore: add debug_assert to new decimal128

---------

Co-authored-by: Dennis Zhuang <[email protected]>
Co-authored-by: Yingwen <[email protected]>
  • Loading branch information
3 people authored Nov 16, 2023
1 parent 9bd1013 commit ae27fbc
Show file tree
Hide file tree
Showing 29 changed files with 961 additions and 82 deletions.
32 changes: 18 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ common-base = { path = "src/common/base" }
common-catalog = { path = "src/common/catalog" }
common-config = { path = "src/common/config" }
common-datasource = { path = "src/common/datasource" }
common-decimal = { path = "src/common/decimal" }
common-error = { path = "src/common/error" }
common-function = { path = "src/common/function" }
common-greptimedb-telemetry = { path = "src/common/greptimedb-telemetry" }
Expand Down
26 changes: 17 additions & 9 deletions src/api/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ impl TryFrom<ConcreteDataType> for ColumnDataTypeWrapper {
},
ConcreteDataType::Null(_)
| ConcreteDataType::List(_)
| ConcreteDataType::Dictionary(_) => {
| ConcreteDataType::Dictionary(_)
| ConcreteDataType::Decimal128(_) => {
return error::IntoColumnDataTypeSnafu { from: datatype }.fail()
}
});
Expand Down Expand Up @@ -341,7 +342,7 @@ pub fn push_vals(column: &mut Column, origin_count: usize, vector: VectorRef) {
TimeUnit::Microsecond => values.duration_microsecond_values.push(val.value()),
TimeUnit::Nanosecond => values.duration_nanosecond_values.push(val.value()),
},
Value::List(_) => unreachable!(),
Value::List(_) | Value::Decimal128(_) => unreachable!(),
});
column.null_mask = null_mask.into_vec();
}
Expand Down Expand Up @@ -522,7 +523,10 @@ pub fn pb_values_to_vector_ref(data_type: &ConcreteDataType, values: Values) ->
values.duration_nanosecond_values,
)),
},
ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) => {
ConcreteDataType::Null(_)
| ConcreteDataType::List(_)
| ConcreteDataType::Dictionary(_)
| ConcreteDataType::Decimal128(_) => {
unreachable!()
}
}
Expand Down Expand Up @@ -692,7 +696,10 @@ pub fn pb_values_to_values(data_type: &ConcreteDataType, values: Values) -> Vec<
.into_iter()
.map(|v| Value::Duration(Duration::new_nanosecond(v)))
.collect(),
ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) => {
ConcreteDataType::Null(_)
| ConcreteDataType::List(_)
| ConcreteDataType::Dictionary(_)
| ConcreteDataType::Decimal128(_) => {
unreachable!()
}
}
Expand Down Expand Up @@ -816,7 +823,7 @@ pub fn to_proto_value(value: Value) -> Option<v1::Value> {
value_data: Some(ValueData::DurationNanosecondValue(v.value())),
},
},
Value::List(_) => return None,
Value::List(_) | Value::Decimal128(_) => return None,
};

Some(proto_value)
Expand Down Expand Up @@ -908,9 +915,10 @@ pub fn to_column_data_type(data_type: &ConcreteDataType) -> Option<ColumnDataTyp
ColumnDataType::IntervalMonthDayNano
}
ConcreteDataType::Interval(IntervalType::DayTime(_)) => ColumnDataType::IntervalDayTime,
ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) => {
return None
}
ConcreteDataType::Null(_)
| ConcreteDataType::List(_)
| ConcreteDataType::Dictionary(_)
| ConcreteDataType::Decimal128(_) => return None,
};

Some(column_data_type)
Expand Down Expand Up @@ -974,7 +982,7 @@ pub fn value_to_grpc_value(value: Value) -> GrpcValue {
TimeUnit::Microsecond => ValueData::DurationMicrosecondValue(v.value()),
TimeUnit::Nanosecond => ValueData::DurationNanosecondValue(v.value()),
}),
Value::List(_) => unreachable!(),
Value::List(_) | Value::Decimal128(_) => unreachable!(),
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/decimal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "decimal"
name = "common-decimal"
version.workspace = true
edition.workspace = true
license.workspace = true
Expand Down
31 changes: 27 additions & 4 deletions src/common/decimal/src/decimal128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,34 @@ const BYTES_TO_OVERFLOW_RUST_DECIMAL: usize = 28;
/// **precision**: the total number of digits in the number, it's range is \[1, 38\].
///
/// **scale**: the number of digits to the right of the decimal point, it's range is \[0, precision\].
#[derive(Debug, Default, Eq, Copy, Clone, Serialize, Deserialize)]
#[derive(Debug, Eq, Copy, Clone, Serialize, Deserialize)]
pub struct Decimal128 {
value: i128,
precision: u8,
scale: i8,
}

impl Decimal128 {
/// Create a new Decimal128 from i128, precision and scale.
pub fn new_unchecked(value: i128, precision: u8, scale: i8) -> Self {
/// Create a new Decimal128 from i128, precision and scale without any validation.
pub fn new(value: i128, precision: u8, scale: i8) -> Self {
// debug assert precision and scale is valid
debug_assert!(
precision > 0 && precision <= DECIMAL128_MAX_PRECISION,
"precision should be in [1, {}]",
DECIMAL128_MAX_PRECISION
);
debug_assert!(
scale >= 0 && scale <= precision as i8,
"scale should be in [0, precision]"
);
Self {
value,
precision,
scale,
}
}

/// Try new Decimal128 from i128, precision and scale with validation.
pub fn try_new(value: i128, precision: u8, scale: i8) -> error::Result<Self> {
// make sure the precision and scale is valid.
valid_precision_and_scale(precision, scale)?;
Expand All @@ -70,6 +81,7 @@ impl Decimal128 {
})
}

/// Return underlying value without precision and scale
pub fn val(&self) -> i128 {
self.value
}
Expand All @@ -90,6 +102,17 @@ impl Decimal128 {
}
}

/// The default value of Decimal128 is 0, and its precision is 1 and scale is 0.
impl Default for Decimal128 {
fn default() -> Self {
Self {
value: 0,
precision: 1,
scale: 0,
}
}
}

impl PartialEq for Decimal128 {
fn eq(&self, other: &Self) -> bool {
self.precision.eq(&other.precision)
Expand Down Expand Up @@ -270,7 +293,7 @@ mod tests {

#[test]
fn test_common_decimal128() {
let decimal = Decimal128::new_unchecked(123456789, 9, 3);
let decimal = Decimal128::new(123456789, 9, 3);
assert_eq!(decimal.to_string(), "123456.789");

let decimal = Decimal128::try_new(123456789, 9, 0);
Expand Down
2 changes: 2 additions & 0 deletions src/common/decimal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@

pub mod decimal128;
pub mod error;

pub use decimal128::Decimal128;
3 changes: 2 additions & 1 deletion src/common/grpc/src/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ macro_rules! convert_arrow_array_to_grpc_vals {
return Ok(vals);
},
)+
ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) => unreachable!("Should not send {:?} in gRPC", $data_type),
// TODO(QuenKar): support gRPC for Decimal128
ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) | ConcreteDataType::Decimal128(_) => unreachable!("Should not send {:?} in gRPC", $data_type),
}
}};
}
Expand Down
2 changes: 2 additions & 0 deletions src/datatypes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ arrow-array.workspace = true
arrow-schema.workspace = true
arrow.workspace = true
common-base.workspace = true
common-decimal.workspace = true
common-error.workspace = true
common-macro.workspace = true
common-telemetry.workspace = true
Expand All @@ -23,6 +24,7 @@ num = "0.4"
num-traits = "0.2"
ordered-float = { version = "3.0", features = ["serde"] }
paste = "1.0"
rust_decimal = "1.32.0"
serde.workspace = true
serde_json = "1.0"
snafu.workspace = true
Loading

0 comments on commit ae27fbc

Please sign in to comment.