andygrove commented on code in PR #615:
URL: https://github.com/apache/datafusion-comet/pull/615#discussion_r1676465313
##########
core/src/execution/datafusion/expressions/cast.rs:
##########
@@ -1208,6 +1277,260 @@ fn do_cast_string_to_int<
Ok(Some(result))
}
+fn cast_string_to_decimal128(
+ str: &str,
+ precision: u8,
+ scale: i8,
+ eval_mode: EvalMode,
+) -> CometResult<Option<i128>> {
+ let cast = match parse_decimal::<Decimal128Type>(str, precision, scale) {
+ Some(v) => v,
+ None => {
+ if eval_mode == EvalMode::Ansi {
+ let type_name = format!("DECIMAL({},{})", precision, scale);
+ return none_or_err(eval_mode, &type_name, str);
+ } else {
+ return Ok(None);
+ }
+ }
+ };
+ Ok(Some(cast))
+}
+
+fn cast_string_to_decimal256(
+ str: &str,
+ precision: u8,
+ scale: i8,
+ eval_mode: EvalMode,
+) -> CometResult<Option<i256>> {
+ let cast = match parse_decimal::<Decimal256Type>(str, precision, scale) {
+ Some(v) => v,
+ None => {
+ if eval_mode == EvalMode::Ansi {
+ let type_name = format!("DECIMAL({},{})", precision, scale);
+ return none_or_err(eval_mode, &type_name, str);
+ } else {
+ return Ok(None);
+ }
+ }
+ };
+ Ok(Some(cast))
+}
+
+/// Copied from arrow-rs, modified to replicate Spark's behavior
+pub fn parse_decimal<T: DecimalType>(s: &str, precision: u8, scale: i8) ->
Option<T::Native> {
+ let mut result: <T as ArrowPrimitiveType>::Native = T::Native::usize_as(0);
+ let mut fractionals = 0;
+ let mut digits: u8 = 0;
+ let mut exponent: i8 = 0;
+ let mut leading_zeros: i8 = 0;
+ let mut has_exponent = false;
+ let mut has_negative_exp = false;
+ let base = T::Native::usize_as(10);
+
+ let bs = s.as_bytes();
+ let (bs, negative) = match bs.first() {
+ Some(b'-') => (&bs[1..], true),
+ Some(b'+') => (&bs[1..], false),
+ _ => (bs, false),
+ };
+
+ if bs.is_empty() {
+ return None;
+ }
+
+ let mut bs = bs.iter();
+ while let Some(b) = bs.next() {
+ match b {
+ b'0'..=b'9' => {
+ if digits == 0 && *b == b'0' {
+ leading_zeros += 1;
+ continue;
+ }
+ digits += 1;
+ result = result.mul_wrapping(base);
+ result = result.add_wrapping(T::Native::usize_as((b - b'0') as
usize));
+ }
+ b'.' => {
+ while let Some(b) = bs.next() {
+ if *b == b'e' || *b == b'E' {
+ match parse_exponent(
+ bs.by_ref(),
+ &mut digits,
+ &mut fractionals,
+ &mut leading_zeros,
+ &mut has_exponent,
+ &mut has_negative_exp,
+ ) {
+ None => {
+ return None;
+ }
+ Some(v) => {
+ exponent = v;
+ continue;
+ }
+ }
+ }
+ if !b.is_ascii_digit() {
+ return None;
+ }
+ fractionals += 1;
+ digits += 1;
+ result = result.mul_wrapping(base);
+ result = result.add_wrapping(T::Native::usize_as((b -
b'0') as usize));
+ }
+
+ // +00. is a valid decimal value in Spark but +. is invalid.
+ if digits == 0 && leading_zeros == 0 {
+ return None;
+ }
+ }
+ b'e' | b'E' => match parse_exponent(
+ &mut bs,
+ &mut digits,
+ &mut fractionals,
+ &mut leading_zeros,
+ &mut has_exponent,
+ &mut has_negative_exp,
+ ) {
+ None => {
+ return None;
+ }
+ Some(v) => {
+ exponent = v;
+ continue;
+ }
+ },
+ _ => {
+ return None;
+ }
+ }
+ }
+
+ result = adjust_decimal_scale::<T>(
+ result,
+ precision,
+ scale,
+ base,
+ exponent,
+ fractionals,
+ digits,
+ has_exponent,
+ has_negative_exp,
+ )?;
+
+ return Some(if negative {
+ result.neg_wrapping()
+ } else {
+ result
+ });
Review Comment:
Because this is the last expression, the `return` here is redundant.
```suggestion
Some(if negative {
result.neg_wrapping()
} else {
result
})
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]