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

uros-b pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 7e875f1ee790 [SPARK-58948][SQL] Deduplicate nulls-buffer creation in 
columnar decompressors
7e875f1ee790 is described below

commit 7e875f1ee79096a95da97f7f1aa52b538baff57a
Author: Uros <[email protected]>
AuthorDate: Mon Aug 24 18:36:39 2026 +0000

    [SPARK-58948][SQL] Deduplicate nulls-buffer creation in columnar 
decompressors
    
    ### What changes were proposed in this pull request?
    
    Each columnar decompressor repeats the same two-line idiom to build the 
"nulls buffer" it reads null-tracking state from:
    
    ```scala
    val nullsBuffer = buffer.duplicate().order(ByteOrder.nativeOrder())
    nullsBuffer.rewind()
    ```
    
    This adds a `createNullsBuffer(buffer: ByteBuffer)` helper to the 
`CompressionScheme` companion object (alongside the existing `columnHeaderSize` 
helper) and routes the six call sites through it (`PassThrough`, 
`RunLengthEncoding`, `DictionaryEncoding`, `BooleanBitSet`, `IntDelta`, 
`LongDelta`). The subsequent `nullCount` / `nextNullIndex` reads stay inline, 
since the `nextNullIndex` sentinel legitimately differs (`-1`, and `capacity` 
for `PassThrough`).
    
    ### Why are the changes needed?
    
    The idiom was duplicated across all six decoders. Naming it once removes 
the duplication and gives a single home for the "duplicate, set native order, 
rewind" convention. It also normalizes the `LongDelta` site, which called 
`rewind` without parentheses.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    Existing columnar compression tests. `createNullsBuffer` returns exactly 
the previously-inlined expression, so decompression behavior is unchanged.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 4.8)
    
    Closes #58228 from uros-b/helper-compressionschemes-nullindex.
    
    Authored-by: Uros <[email protected]>
    Signed-off-by: Uros Bojanic <[email protected]>
---
 .../columnar/compression/CompressionScheme.scala      |  6 ++++++
 .../columnar/compression/compressionSchemes.scala     | 19 ++++++-------------
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/columnar/compression/CompressionScheme.scala
 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/columnar/compression/CompressionScheme.scala
index 0fe1fbcf9450..e0f68a70daae 100644
--- 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/columnar/compression/CompressionScheme.scala
+++ 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/columnar/compression/CompressionScheme.scala
@@ -84,4 +84,10 @@ private[columnar] object CompressionScheme {
     // null count + null positions
     4 + 4 * nullCount
   }
+
+  def createNullsBuffer(buffer: ByteBuffer): ByteBuffer = {
+    val nullsBuffer = buffer.duplicate().order(ByteOrder.nativeOrder())
+    nullsBuffer.rewind()
+    nullsBuffer
+  }
 }
diff --git 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/columnar/compression/compressionSchemes.scala
 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/columnar/compression/compressionSchemes.scala
index 86d76856e12b..72bebb96ed3a 100644
--- 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/columnar/compression/compressionSchemes.scala
+++ 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/columnar/compression/compressionSchemes.scala
@@ -18,7 +18,6 @@
 package org.apache.spark.sql.execution.columnar.compression
 
 import java.nio.ByteBuffer
-import java.nio.ByteOrder
 
 import scala.collection.mutable
 
@@ -108,8 +107,7 @@ private[columnar] case object PassThrough extends 
CompressionScheme {
         capacity: Int,
         unitSize: Int,
         putFunction: (WritableColumnVector, Int, Int, Int) => Unit): Unit = {
-      val nullsBuffer = buffer.duplicate().order(ByteOrder.nativeOrder())
-      nullsBuffer.rewind()
+      val nullsBuffer = CompressionScheme.createNullsBuffer(buffer)
       val nullCount = ByteBufferHelper.getInt(nullsBuffer)
       var nextNullIndex = if (nullCount > 0) 
ByteBufferHelper.getInt(nullsBuffer) else capacity
       var pos = 0
@@ -307,8 +305,7 @@ private[columnar] case object RunLengthEncoding extends 
CompressionScheme {
         capacity: Int,
         getFunction: (ByteBuffer) => Long,
         putFunction: (WritableColumnVector, Int, Long) => Unit): Unit = {
-      val nullsBuffer = buffer.duplicate().order(ByteOrder.nativeOrder())
-      nullsBuffer.rewind()
+      val nullsBuffer = CompressionScheme.createNullsBuffer(buffer)
       val nullCount = ByteBufferHelper.getInt(nullsBuffer)
       var nextNullIndex = if (nullCount > 0) 
ByteBufferHelper.getInt(nullsBuffer) else -1
       var pos = 0
@@ -486,8 +483,7 @@ private[columnar] case object DictionaryEncoding extends 
CompressionScheme {
     override def hasNext: Boolean = buffer.hasRemaining
 
     override def decompress(columnVector: WritableColumnVector, capacity: 
Int): Unit = {
-      val nullsBuffer = buffer.duplicate().order(ByteOrder.nativeOrder())
-      nullsBuffer.rewind()
+      val nullsBuffer = CompressionScheme.createNullsBuffer(buffer)
       val nullCount = ByteBufferHelper.getInt(nullsBuffer)
       var nextNullIndex = if (nullCount > 0) 
ByteBufferHelper.getInt(nullsBuffer) else -1
       var pos = 0
@@ -619,8 +615,7 @@ private[columnar] case object BooleanBitSet extends 
CompressionScheme {
     override def decompress(columnVector: WritableColumnVector, capacity: 
Int): Unit = {
       var currentWordLocal: Long = 0
       var visitedLocal: Int = 0
-      val nullsBuffer = buffer.duplicate().order(ByteOrder.nativeOrder())
-      nullsBuffer.rewind()
+      val nullsBuffer = CompressionScheme.createNullsBuffer(buffer)
       val nullCount = ByteBufferHelper.getInt(nullsBuffer)
       var nextNullIndex = if (nullCount > 0) 
ByteBufferHelper.getInt(nullsBuffer) else -1
       var pos = 0
@@ -730,8 +725,7 @@ private[columnar] case object IntDelta extends 
CompressionScheme {
 
     override def decompress(columnVector: WritableColumnVector, capacity: 
Int): Unit = {
       var prevLocal: Int = 0
-      val nullsBuffer = buffer.duplicate().order(ByteOrder.nativeOrder())
-      nullsBuffer.rewind()
+      val nullsBuffer = CompressionScheme.createNullsBuffer(buffer)
       val nullCount = ByteBufferHelper.getInt(nullsBuffer)
       var nextNullIndex = if (nullCount > 0) 
ByteBufferHelper.getInt(nullsBuffer) else -1
       var pos = 0
@@ -837,8 +831,7 @@ private[columnar] case object LongDelta extends 
CompressionScheme {
 
     override def decompress(columnVector: WritableColumnVector, capacity: 
Int): Unit = {
       var prevLocal: Long = 0
-      val nullsBuffer = buffer.duplicate().order(ByteOrder.nativeOrder())
-      nullsBuffer.rewind
+      val nullsBuffer = CompressionScheme.createNullsBuffer(buffer)
       val nullCount = ByteBufferHelper.getInt(nullsBuffer)
       var nextNullIndex = if (nullCount > 0) 
ByteBufferHelper.getInt(nullsBuffer) else -1
       var pos = 0


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

Reply via email to