From 350db41f5e8b8fba0d01543454f33870e1866b76 Mon Sep 17 00:00:00 2001 From: TAQI RAZA Date: Mon, 12 Oct 2026 00:00:53 +0000 Subject: [PATCH] fix: resolve #1659 - Support ANSI SQL null semantics and evaluation for IN clause --- dozer-sql/expression/src/in_list.rs | 11 +++++++- dozer-sql/src/expression/tests/in_list.rs | 32 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/dozer-sql/expression/src/in_list.rs b/dozer-sql/expression/src/in_list.rs index d538214d65..3bb0009823 100644 --- a/dozer-sql/expression/src/in_list.rs +++ b/dozer-sql/expression/src/in_list.rs @@ -12,14 +12,23 @@ pub(crate) fn evaluate_in_list( record: &Record, ) -> Result { let field = expr.evaluate(record, schema)?; + if field == Field::Null { + return Ok(Field::Null); + } let mut result = false; + let mut has_null = false; for item in list { let item = item.evaluate(record, schema)?; - if field == item { + if item == Field::Null { + has_null = true; + } else if field == item { result = true; break; } } + if !result && has_null { + return Ok(Field::Null); + } // Negate the result if the IN list was negated. if negated { result = !result; diff --git a/dozer-sql/src/expression/tests/in_list.rs b/dozer-sql/src/expression/tests/in_list.rs index 0296f2210c..52cedbe1be 100644 --- a/dozer-sql/src/expression/tests/in_list.rs +++ b/dozer-sql/src/expression/tests/in_list.rs @@ -84,3 +84,35 @@ fn test_not_in_list() { ); assert_eq!(f, Field::Boolean(false)); } + + +#[test] +fn test_in_list_null_semantics() { + let f = run_fct( + "SELECT NULL IN (1, 2, 3)", + Schema::default(), + vec![], + ); + assert_eq!(f, Field::Null); + + let f = run_fct( + "SELECT 42 IN (1, 2, NULL)", + Schema::default(), + vec![], + ); + assert_eq!(f, Field::Null); + + let f = run_fct( + "SELECT 42 NOT IN (1, 2, NULL)", + Schema::default(), + vec![], + ); + assert_eq!(f, Field::Null); + + let f = run_fct( + "SELECT 42 IN (1, 2, 42, NULL)", + Schema::default(), + vec![], + ); + assert_eq!(f, Field::Boolean(true)); +}