This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new a8d1af6b8a fix: prevent LEAD/LAG IGNORE NULLS panic without null 
bitmap (#23706)
a8d1af6b8a is described below

commit a8d1af6b8a82ded56eb547ad698b224c1f8bf7be
Author: xudong.w <[email protected]>
AuthorDate: Mon Jul 20 12:09:26 2026 +0800

    fix: prevent LEAD/LAG IGNORE NULLS panic without null bitmap (#23706)
    
    ## Which issue does this PR close?
    
    - Closes #23705.
    
    ## Rationale for this change
    
    Arrow arrays containing no null values commonly omit the null bitmap.
    The whole-partition evaluation path for `LEAD` and `LAG` with `IGNORE
    NULLS` unconditionally unwrapped that optional bitmap, causing a panic
    for valid non-null input arrays.
    
    ## What changes are included in this PR?
    
    - Fall back to the existing regular shift implementation when the input
    has no null bitmap.
    - Add a regression test covering both `LEAD` and `LAG` with an array
    that explicitly has no null bitmap.
    
    ## Are these changes tested?
    
    Yes.
    
    
    
    ## Are there any user-facing changes?
    
    `LEAD` and `LAG` with `IGNORE NULLS` no longer panic when the input
    Arrow array has no null bitmap. There are no public API changes.
---
 datafusion/functions-window/src/lead_lag.rs | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/datafusion/functions-window/src/lead_lag.rs 
b/datafusion/functions-window/src/lead_lag.rs
index de4071c0ce..2363a6beed 100644
--- a/datafusion/functions-window/src/lead_lag.rs
+++ b/datafusion/functions-window/src/lead_lag.rs
@@ -433,8 +433,12 @@ fn evaluate_all_with_ignore_null(
     default_value: &ScalarValue,
     is_lag: bool,
 ) -> Result<ArrayRef, DataFusionError> {
-    let valid_indices: Vec<usize> =
-        array.nulls().unwrap().valid_indices().collect::<Vec<_>>();
+    // Arrays without NULLs do not necessarily have a null bitmap.
+    let Some(nulls) = array.nulls() else {
+        return shift_with_default_value(array, offset, default_value);
+    };
+
+    let valid_indices: Vec<usize> = nulls.valid_indices().collect::<Vec<_>>();
     let direction = !is_lag;
     let new_array_results: Result<Vec<_>, DataFusionError> = (0..array.len())
         .map(|id| {
@@ -838,4 +842,25 @@ mod tests {
             .collect::<Int32Array>(),
         )
     }
+
+    #[test]
+    fn test_ignore_nulls_without_null_bitmap() -> Result<()> {
+        let input = Int32Array::from(vec![1, 2, 3]);
+        assert!(input.nulls().is_none());
+        let input: ArrayRef = Arc::new(input);
+
+        for (offset, expected) in [
+            (1, Int32Array::from(vec![None, Some(1), Some(2)])),
+            (-1, Int32Array::from(vec![Some(2), Some(3), None])),
+        ] {
+            let actual = evaluate_all_with_ignore_null(
+                &input,
+                offset,
+                &ScalarValue::Int32(None),
+                offset > 0,
+            )?;
+            assert_eq!(expected, *as_int32_array(&actual)?);
+        }
+        Ok(())
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to