From dd301384d9be16614f07308cad3b73da8313fd0c Mon Sep 17 00:00:00 2001 From: discord9 Date: Tue, 3 Mar 2026 20:52:12 +0800 Subject: [PATCH] fix: null first for part expr as logical expr Signed-off-by: discord9 --- src/partition/src/expr.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/partition/src/expr.rs b/src/partition/src/expr.rs index 1e7b573acb..75e440b979 100644 --- a/src/partition/src/expr.rs +++ b/src/partition/src/expr.rs @@ -301,28 +301,39 @@ impl PartitionExpr { self.op, RestrictedOp::Lt | RestrictedOp::LtEq | RestrictedOp::Gt | RestrictedOp::GtEq ) { + // make sure null first for consistent logical expression when null is involved. + // As in src/datatypes/src/value.rs, Value::Null is considered less than any other value. if matches!(self.lhs.as_ref(), Operand::Column(_)) { let column_expr = self.lhs.try_as_logical_expr()?; let other_expr = self.rhs.try_as_logical_expr()?; let base = match self.op { - RestrictedOp::Lt => column_expr.clone().lt(other_expr), - RestrictedOp::LtEq => column_expr.clone().lt_eq(other_expr), + RestrictedOp::Lt => { + column_expr.clone().lt(other_expr).or(column_expr.is_null()) + } + RestrictedOp::LtEq => column_expr + .clone() + .lt_eq(other_expr) + .or(column_expr.is_null()), RestrictedOp::Gt => column_expr.clone().gt(other_expr), RestrictedOp::GtEq => column_expr.clone().gt_eq(other_expr), _ => unreachable!(), }; - return Ok(datafusion_expr::or(base, column_expr.is_null())); + return Ok(base); } else if matches!(self.rhs.as_ref(), Operand::Column(_)) { let other_expr = self.lhs.try_as_logical_expr()?; let column_expr = self.rhs.try_as_logical_expr()?; let base = match self.op { RestrictedOp::Lt => other_expr.lt(column_expr.clone()), RestrictedOp::LtEq => other_expr.lt_eq(column_expr.clone()), - RestrictedOp::Gt => other_expr.gt(column_expr.clone()), - RestrictedOp::GtEq => other_expr.gt_eq(column_expr.clone()), + RestrictedOp::Gt => { + other_expr.gt(column_expr.clone()).or(column_expr.is_null()) + } + RestrictedOp::GtEq => other_expr + .gt_eq(column_expr.clone()) + .or(column_expr.is_null()), _ => unreachable!(), }; - return Ok(datafusion_expr::or(base, column_expr.is_null())); + return Ok(base); } }