Skip to content

Commit

Permalink
feat: Add IS NULL expression (#2468)
Browse files Browse the repository at this point in the history
  • Loading branch information
mediuminvader authored Mar 26, 2024
1 parent 529182a commit f155736
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
27 changes: 27 additions & 0 deletions dozer-sql/expression/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ impl ExpressionBuilder {
)
.await
}
SqlExpr::IsNull(expr) => {
self.parse_sql_isnull_operator(parse_aggregations, &false, expr, schema, udfs)
.await
}
SqlExpr::IsNotNull(expr) => {
self.parse_sql_isnull_operator(parse_aggregations, &true, expr, schema, udfs)
.await
}
_ => Err(Error::UnsupportedExpression(expression.clone())),
}
}
Expand Down Expand Up @@ -1014,6 +1022,25 @@ impl ExpressionBuilder {

Ok(in_list_expression)
}

async fn parse_sql_isnull_operator(
&mut self,
parse_aggregations: bool,
negated: &bool,
expr: &Expr,
schema: &Schema,
udfs: &[UdfConfig],
) -> Result<Expression, Error> {
let arg = self
.parse_sql_expression(parse_aggregations, expr, schema, udfs)
.await?;

if *negated {
Ok(Expression::IsNotNull { arg: Box::new(arg) })
} else {
Ok(Expression::IsNull { arg: Box::new(arg) })
}
}
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
Expand Down
23 changes: 23 additions & 0 deletions dozer-sql/expression/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::conditional::{get_conditional_expr_type, ConditionalExpressionType};
use crate::datetime::{get_datetime_function_type, DateTimeFunctionType};
use crate::error::Error;
use crate::geo::common::{get_geo_function_type, GeoFunctionType};
use crate::is_null::{evaluate_is_not_null, evaluate_is_null};
use crate::json_functions::JsonFunctionType;
use crate::operator::{BinaryOperatorType, UnaryOperatorType};
use crate::scalar::common::{get_scalar_function_type, ScalarFunctionType};
Expand Down Expand Up @@ -84,6 +85,12 @@ pub enum Expression {
results: Vec<Expression>,
else_result: Option<Box<Expression>>,
},
IsNull {
arg: Box<Expression>,
},
IsNotNull {
arg: Box<Expression>,
},
#[cfg(feature = "python")]
PythonUDF {
name: String,
Expand Down Expand Up @@ -278,6 +285,8 @@ impl Expression {
}
#[cfg(feature = "javascript")]
Expression::JavaScriptUdf(udf) => udf.to_string(schema),
Expression::IsNull { arg } => arg.to_string(schema) + " IS NULL ",
Expression::IsNotNull { arg } => arg.to_string(schema) + " IS NOT NULL ",
}
}
}
Expand Down Expand Up @@ -365,6 +374,8 @@ impl Expression {
results,
else_result,
} => evaluate_case(schema, operand, conditions, results, else_result, record),
Expression::IsNull { arg } => evaluate_is_null(schema, arg, record),
Expression::IsNotNull { arg } => evaluate_is_not_null(schema, arg, record),
#[cfg(feature = "javascript")]
Expression::JavaScriptUdf(udf) => udf.evaluate(record, schema),
}
Expand Down Expand Up @@ -476,6 +487,18 @@ impl Expression {
)),
#[cfg(feature = "javascript")]
Expression::JavaScriptUdf(udf) => Ok(udf.get_type()),
Expression::IsNull { arg: _ } => Ok(ExpressionType::new(
FieldType::Boolean,
false,
SourceDefinition::Dynamic,
false,
)),
Expression::IsNotNull { arg: _ } => Ok(ExpressionType::new(
FieldType::Boolean,
false,
SourceDefinition::Dynamic,
false,
)),
}
}
}
Expand Down
50 changes: 50 additions & 0 deletions dozer-sql/expression/src/is_null.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use dozer_types::types::Record;
use dozer_types::types::{Field, Schema};

use crate::error::Error;
use crate::execution::Expression;

pub(crate) fn evaluate_is_null(
schema: &Schema,
expr: &mut Expression,
record: &Record,
) -> Result<Field, Error> {
let field = expr.evaluate(record, schema)?;
Ok(Field::Boolean(field == Field::Null))
}

pub(crate) fn evaluate_is_not_null(
schema: &Schema,
expr: &mut Expression,
record: &Record,
) -> Result<Field, Error> {
let field = expr.evaluate(record, schema)?;
Ok(Field::Boolean(field != Field::Null))
}

#[test]
fn test_is_null() {
let mut value = Box::new(Expression::Literal(Field::Int(65)));
assert_eq!(
evaluate_is_null(&Schema::default(), &mut value, &Record::new(vec![])).unwrap(),
Field::Boolean(false)
);

let mut value = Box::new(Expression::Literal(Field::Null));
assert_eq!(
evaluate_is_null(&Schema::default(), &mut value, &Record::new(vec![])).unwrap(),
Field::Boolean(true)
);

let mut value = Box::new(Expression::Literal(Field::Int(65)));
assert_eq!(
evaluate_is_not_null(&Schema::default(), &mut value, &Record::new(vec![])).unwrap(),
Field::Boolean(true)
);

let mut value = Box::new(Expression::Literal(Field::Null));
assert_eq!(
evaluate_is_not_null(&Schema::default(), &mut value, &Record::new(vec![])).unwrap(),
Field::Boolean(false)
);
}
1 change: 1 addition & 0 deletions dozer-sql/expression/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod error;
pub mod execution;
mod geo;
mod in_list;
mod is_null;
mod json_functions;
mod logical;
mod mathematical;
Expand Down

0 comments on commit f155736

Please sign in to comment.