Skip to content

Commit edbe6a8

Browse files
committed
feat: Support decimal math with scalar
Signed-off-by: Alex Qyoun-ae <[email protected]>
1 parent 96c5f17 commit edbe6a8

File tree

1 file changed

+76
-0
lines changed
  • datafusion/physical-expr/src/expressions

1 file changed

+76
-0
lines changed

datafusion/physical-expr/src/expressions/binary.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,19 @@ fn is_not_distinct_from_decimal(
322322
Ok(bool_builder.finish())
323323
}
324324

325+
fn add_decimal_scalar(left: &DecimalArray, right: i128) -> Result<DecimalArray> {
326+
let mut decimal_builder =
327+
DecimalBuilder::new(left.len(), left.precision(), left.scale());
328+
for i in 0..left.len() {
329+
if left.is_null(i) {
330+
decimal_builder.append_null()?;
331+
} else {
332+
decimal_builder.append_value(left.value(i) + right)?;
333+
}
334+
}
335+
Ok(decimal_builder.finish())
336+
}
337+
325338
fn add_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<DecimalArray> {
326339
let mut decimal_builder =
327340
DecimalBuilder::new(left.len(), left.precision(), left.scale());
@@ -335,6 +348,19 @@ fn add_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<DecimalArray
335348
Ok(decimal_builder.finish())
336349
}
337350

351+
fn subtract_decimal_scalar(left: &DecimalArray, right: i128) -> Result<DecimalArray> {
352+
let mut decimal_builder =
353+
DecimalBuilder::new(left.len(), left.precision(), left.scale());
354+
for i in 0..left.len() {
355+
if left.is_null(i) {
356+
decimal_builder.append_null()?;
357+
} else {
358+
decimal_builder.append_value(left.value(i) - right)?;
359+
}
360+
}
361+
Ok(decimal_builder.finish())
362+
}
363+
338364
fn subtract_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<DecimalArray> {
339365
let mut decimal_builder =
340366
DecimalBuilder::new(left.len(), left.precision(), left.scale());
@@ -348,6 +374,20 @@ fn subtract_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<Decimal
348374
Ok(decimal_builder.finish())
349375
}
350376

377+
fn multiply_decimal_scalar(left: &DecimalArray, right: i128) -> Result<DecimalArray> {
378+
let mut decimal_builder =
379+
DecimalBuilder::new(left.len(), left.precision(), left.scale());
380+
let divide = 10_i128.pow(left.scale() as u32);
381+
for i in 0..left.len() {
382+
if left.is_null(i) {
383+
decimal_builder.append_null()?;
384+
} else {
385+
decimal_builder.append_value(left.value(i) * right / divide)?;
386+
}
387+
}
388+
Ok(decimal_builder.finish())
389+
}
390+
351391
fn multiply_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<DecimalArray> {
352392
let mut decimal_builder =
353393
DecimalBuilder::new(left.len(), left.precision(), left.scale());
@@ -362,6 +402,24 @@ fn multiply_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<Decimal
362402
Ok(decimal_builder.finish())
363403
}
364404

405+
fn divide_decimal_scalar(left: &DecimalArray, right: i128) -> Result<DecimalArray> {
406+
let mut decimal_builder =
407+
DecimalBuilder::new(left.len(), left.precision(), left.scale());
408+
let mul = 10_f64.powi(left.scale() as i32);
409+
for i in 0..left.len() {
410+
if left.is_null(i) {
411+
decimal_builder.append_null()?;
412+
} else if right == 0 {
413+
return Err(DataFusionError::ArrowError(DivideByZero));
414+
} else {
415+
let l_value = left.value(i) as f64;
416+
let result = ((l_value / right as f64) * mul) as i128;
417+
decimal_builder.append_value(result)?;
418+
}
419+
}
420+
Ok(decimal_builder.finish())
421+
}
422+
365423
fn divide_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<DecimalArray> {
366424
let mut decimal_builder =
367425
DecimalBuilder::new(left.len(), left.precision(), left.scale());
@@ -381,6 +439,21 @@ fn divide_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<DecimalAr
381439
Ok(decimal_builder.finish())
382440
}
383441

442+
fn modulus_decimal_scalar(left: &DecimalArray, right: i128) -> Result<DecimalArray> {
443+
let mut decimal_builder =
444+
DecimalBuilder::new(left.len(), left.precision(), left.scale());
445+
for i in 0..left.len() {
446+
if left.is_null(i) {
447+
decimal_builder.append_null()?;
448+
} else if right == 0 {
449+
return Err(DataFusionError::ArrowError(DivideByZero));
450+
} else {
451+
decimal_builder.append_value(left.value(i) % right)?;
452+
}
453+
}
454+
Ok(decimal_builder.finish())
455+
}
456+
384457
fn modulus_decimal(left: &DecimalArray, right: &DecimalArray) -> Result<DecimalArray> {
385458
let mut decimal_builder =
386459
DecimalBuilder::new(left.len(), left.precision(), left.scale());
@@ -1049,6 +1122,9 @@ macro_rules! binary_primitive_array_op {
10491122
macro_rules! binary_primitive_array_op_scalar {
10501123
($LEFT:expr, $RIGHT:expr, $OP:ident) => {{
10511124
let result: Result<Arc<dyn Array>> = match $LEFT.data_type() {
1125+
// TODO support decimal type
1126+
// which is not the primitive type
1127+
DataType::Decimal(_,_) => compute_decimal_op_scalar!($LEFT, $RIGHT, $OP, DecimalArray),
10521128
DataType::Int8 => compute_op_scalar!($LEFT, $RIGHT, $OP, Int8Array),
10531129
DataType::Int16 => compute_op_scalar!($LEFT, $RIGHT, $OP, Int16Array),
10541130
DataType::Int32 => compute_op_scalar!($LEFT, $RIGHT, $OP, Int32Array),

0 commit comments

Comments
 (0)