Skip to content
155 changes: 155 additions & 0 deletions native/core/src/execution/expressions/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

//! Arithmetic expression builders

/// Macro to generate arithmetic expression builders that need eval_mode handling
#[macro_export]
macro_rules! arithmetic_expr_builder {
($builder_name:ident, $expr_type:ident, $operator:expr) => {
pub struct $builder_name;

impl $crate::execution::planner::traits::ExpressionBuilder for $builder_name {
fn build(
&self,
spark_expr: &datafusion_comet_proto::spark_expression::Expr,
input_schema: arrow::datatypes::SchemaRef,
planner: &$crate::execution::planner::PhysicalPlanner,
) -> Result<
std::sync::Arc<dyn datafusion::physical_expr::PhysicalExpr>,
$crate::execution::operators::ExecutionError,
> {
let expr = $crate::extract_expr!(spark_expr, $expr_type);
let eval_mode =
$crate::execution::planner::from_protobuf_eval_mode(expr.eval_mode)?;
planner.create_binary_expr(
expr.left.as_ref().unwrap(),
expr.right.as_ref().unwrap(),
expr.return_type.as_ref(),
$operator,
input_schema,
eval_mode,
)
}
}
};
}

use std::sync::Arc;

use arrow::datatypes::SchemaRef;
use datafusion::logical_expr::Operator as DataFusionOperator;
use datafusion::physical_expr::PhysicalExpr;
use datafusion_comet_proto::spark_expression::Expr;
use datafusion_comet_spark_expr::{create_modulo_expr, create_negate_expr, EvalMode};

use crate::execution::{
expressions::extract_expr,
operators::ExecutionError,
planner::{
from_protobuf_eval_mode, traits::ExpressionBuilder, BinaryExprOptions, PhysicalPlanner,
},
};

/// Macro to define basic arithmetic builders that use eval_mode
macro_rules! define_basic_arithmetic_builders {
($(($builder:ident, $expr_type:ident, $op:expr)),* $(,)?) => {
$(
arithmetic_expr_builder!($builder, $expr_type, $op);
)*
};
}

define_basic_arithmetic_builders![
(AddBuilder, Add, DataFusionOperator::Plus),
(SubtractBuilder, Subtract, DataFusionOperator::Minus),
(MultiplyBuilder, Multiply, DataFusionOperator::Multiply),
(DivideBuilder, Divide, DataFusionOperator::Divide),
];

/// Builder for IntegralDivide expressions (requires special options)
pub struct IntegralDivideBuilder;

impl ExpressionBuilder for IntegralDivideBuilder {
fn build(
&self,
spark_expr: &Expr,
input_schema: SchemaRef,
planner: &PhysicalPlanner,
) -> Result<Arc<dyn PhysicalExpr>, ExecutionError> {
let expr = extract_expr!(spark_expr, IntegralDivide);
let eval_mode = from_protobuf_eval_mode(expr.eval_mode)?;
planner.create_binary_expr_with_options(
expr.left.as_ref().unwrap(),
expr.right.as_ref().unwrap(),
expr.return_type.as_ref(),
DataFusionOperator::Divide,
input_schema,
BinaryExprOptions {
is_integral_div: true,
},
eval_mode,
)
}
}

/// Builder for Remainder expressions (uses special modulo function)
pub struct RemainderBuilder;

impl ExpressionBuilder for RemainderBuilder {
fn build(
&self,
spark_expr: &Expr,
input_schema: SchemaRef,
planner: &PhysicalPlanner,
) -> Result<Arc<dyn PhysicalExpr>, ExecutionError> {
let expr = extract_expr!(spark_expr, Remainder);
let eval_mode = from_protobuf_eval_mode(expr.eval_mode)?;
let left = planner.create_expr(expr.left.as_ref().unwrap(), Arc::clone(&input_schema))?;
let right = planner.create_expr(expr.right.as_ref().unwrap(), Arc::clone(&input_schema))?;

let result = create_modulo_expr(
left,
right,
expr.return_type
.as_ref()
.map(crate::execution::serde::to_arrow_datatype)
.unwrap(),
input_schema,
eval_mode == EvalMode::Ansi,
&planner.session_ctx().state(),
);
result.map_err(|e| ExecutionError::GeneralError(e.to_string()))
}
}

/// Builder for UnaryMinus expressions (uses special negate function)
pub struct UnaryMinusBuilder;

impl ExpressionBuilder for UnaryMinusBuilder {
fn build(
&self,
spark_expr: &Expr,
input_schema: SchemaRef,
planner: &PhysicalPlanner,
) -> Result<Arc<dyn PhysicalExpr>, ExecutionError> {
let expr = extract_expr!(spark_expr, UnaryMinus);
let child = planner.create_expr(expr.child.as_ref().unwrap(), input_schema)?;
let result = create_negate_expr(child, expr.fail_on_error);
result.map_err(|e| ExecutionError::GeneralError(e.to_string()))
}
}
55 changes: 55 additions & 0 deletions native/core/src/execution/expressions/bitwise.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

//! Bitwise expression builders

use datafusion::logical_expr::Operator as DataFusionOperator;

use crate::binary_expr_builder;

/// Macro to define all bitwise builders at once
macro_rules! define_bitwise_builders {
($(($builder:ident, $expr_type:ident, $op:expr)),* $(,)?) => {
$(
binary_expr_builder!($builder, $expr_type, $op);
)*
};
}

define_bitwise_builders![
(
BitwiseAndBuilder,
BitwiseAnd,
DataFusionOperator::BitwiseAnd
),
(BitwiseOrBuilder, BitwiseOr, DataFusionOperator::BitwiseOr),
(
BitwiseXorBuilder,
BitwiseXor,
DataFusionOperator::BitwiseXor
),
(
BitwiseShiftLeftBuilder,
BitwiseShiftLeft,
DataFusionOperator::BitwiseShiftLeft
),
(
BitwiseShiftRightBuilder,
BitwiseShiftRight,
DataFusionOperator::BitwiseShiftRight
),
];
50 changes: 50 additions & 0 deletions native/core/src/execution/expressions/comparison.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

//! Comparison expression builders

use datafusion::logical_expr::Operator as DataFusionOperator;

use crate::binary_expr_builder;

/// Macro to define all comparison builders at once
macro_rules! define_comparison_builders {
($(($builder:ident, $expr_type:ident, $op:expr)),* $(,)?) => {
$(
binary_expr_builder!($builder, $expr_type, $op);
)*
};
}

define_comparison_builders![
(EqBuilder, Eq, DataFusionOperator::Eq),
(NeqBuilder, Neq, DataFusionOperator::NotEq),
(LtBuilder, Lt, DataFusionOperator::Lt),
(LtEqBuilder, LtEq, DataFusionOperator::LtEq),
(GtBuilder, Gt, DataFusionOperator::Gt),
(GtEqBuilder, GtEq, DataFusionOperator::GtEq),
(
EqNullSafeBuilder,
EqNullSafe,
DataFusionOperator::IsNotDistinctFrom
),
(
NeqNullSafeBuilder,
NeqNullSafe,
DataFusionOperator::IsDistinctFrom
),
];
34 changes: 34 additions & 0 deletions native/core/src/execution/expressions/logical.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

//! Logical expression builders

use datafusion::logical_expr::Operator as DataFusionOperator;
use datafusion::physical_expr::expressions::NotExpr;

use crate::{binary_expr_builder, unary_expr_builder};

/// Macro to define all logical builders at once
macro_rules! define_logical_builders {
() => {
binary_expr_builder!(AndBuilder, And, DataFusionOperator::And);
binary_expr_builder!(OrBuilder, Or, DataFusionOperator::Or);
unary_expr_builder!(NotBuilder, Not, NotExpr::new);
};
}

define_logical_builders!();
8 changes: 8 additions & 0 deletions native/core/src/execution/expressions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@

//! Native DataFusion expressions

pub mod arithmetic;
pub mod bitwise;
pub mod comparison;
pub mod logical;
pub mod nullcheck;
pub mod subquery;

pub use datafusion_comet_spark_expr::EvalMode;

// Re-export the extract_expr macro for convenience in expression builders
pub use crate::extract_expr;
32 changes: 32 additions & 0 deletions native/core/src/execution/expressions/nullcheck.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

//! Null check expression builders

use datafusion::physical_expr::expressions::{IsNotNullExpr, IsNullExpr};

use crate::unary_expr_builder;

/// Macro to define all null check builders at once
macro_rules! define_null_check_builders {
() => {
unary_expr_builder!(IsNullBuilder, IsNull, IsNullExpr::new);
unary_expr_builder!(IsNotNullBuilder, IsNotNull, IsNotNullExpr::new);
};
}

define_null_check_builders!();
Loading
Loading