1616
1717package com .nvidia .spark .rapids
1818
19- import scala .collection .mutable .ArrayBuffer
20-
2119import ai .rapids .cudf .Table
2220import com .nvidia .spark .rapids .Arm .{closeOnExcept , withResource }
2321import com .nvidia .spark .rapids .GpuMetric ._
@@ -35,12 +33,14 @@ import org.apache.spark.sql.catalyst.plans.physical.{AllTuples, Distribution, Pa
3533import org .apache .spark .sql .catalyst .util .truncatedString
3634import org .apache .spark .sql .execution .{CollectLimitExec , LimitExec , SparkPlan , TakeOrderedAndProjectExec }
3735import org .apache .spark .sql .execution .exchange .ENSURE_REQUIREMENTS
36+ import org .apache .spark .sql .types .{DataType , StructField , StructType }
3837import org .apache .spark .sql .vectorized .{ColumnarBatch , ColumnVector }
3938
4039class GpuBaseLimitIterator (
4140 input : Iterator [ColumnarBatch ],
4241 limit : Int ,
4342 offset : Int ,
43+ dataTypes : Array [DataType ],
4444 opTime : GpuMetric ,
4545 numOutputBatches : GpuMetric ,
4646 numOutputRows : GpuMetric ) extends Iterator [ColumnarBatch ] {
@@ -55,7 +55,6 @@ class GpuBaseLimitIterator(
5555 }
5656
5757 var batch = input.next()
58- val numCols = batch.numCols()
5958
6059 // In each partition, we need to skip `offset` rows
6160 while (batch != null && remainingOffset >= batch.numRows()) {
@@ -71,7 +70,10 @@ class GpuBaseLimitIterator(
7170 // If the last batch is null, then we have offset >= numRows in this partition.
7271 // In such case, we should return an empty batch
7372 if (batch == null || batch.numRows() == 0 ) {
74- return new ColumnarBatch (new ArrayBuffer [GpuColumnVector ](numCols).toArray, 0 )
73+ val fields = dataTypes.zipWithIndex.map {
74+ case (dt, idx) => StructField (s " _col $idx" , dt, nullable = true )
75+ }
76+ return GpuColumnVector .emptyBatch(StructType (fields))
7577 }
7678
7779 // Here 0 <= remainingOffset < batch.numRow(), we need to get batch[remainingOffset:]
@@ -156,7 +158,8 @@ trait GpuBaseLimitExec extends LimitExec with GpuExec with ShimUnaryExecNode {
156158 val numOutputRows = gpuLongMetric(NUM_OUTPUT_ROWS )
157159 val numOutputBatches = gpuLongMetric(NUM_OUTPUT_BATCHES )
158160 rdd.mapPartitions { iter =>
159- new GpuBaseLimitIterator (iter, limit, offset, opTime, numOutputBatches, numOutputRows)
161+ new GpuBaseLimitIterator (iter, limit, offset, output.map(_.dataType).toArray,
162+ opTime, numOutputBatches, numOutputRows)
160163 }
161164 }
162165
0 commit comments