Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,19 @@ public void testZeroRowResultSet() throws Exception {
.setReuseVectorSchemaRoot(reuseVectorSchemaRoot)
.build();

ArrowVectorIterator iter = JdbcToArrow.sqlToArrowVectorIterator(rs, config);
assertTrue(iter.hasNext(), "Iterator on zero row ResultSet should haveNext() before use");
VectorSchemaRoot root = iter.next();
assertNotNull(root, "VectorSchemaRoot from first next() result should never be null");
assertEquals(
0, root.getRowCount(), "VectorSchemaRoot from empty ResultSet should have zero rows");
assertFalse(
iter.hasNext(),
"hasNext() should return false on empty ResultSets after initial next() call");
try (ArrowVectorIterator iter = JdbcToArrow.sqlToArrowVectorIterator(rs, config)) {
assertTrue(iter.hasNext(), "Iterator on zero row ResultSet should haveNext() before use");
VectorSchemaRoot root = iter.next();
assertNotNull(root, "VectorSchemaRoot from first next() result should never be null");
assertEquals(
0, root.getRowCount(), "VectorSchemaRoot from empty ResultSet should have zero rows");
assertFalse(
iter.hasNext(),
"hasNext() should return false on empty ResultSets after initial next() call");
if (!reuseVectorSchemaRoot) {
root.close();
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,26 @@ private void setReaderAndWriterIndex() {
valueBuffer.readerIndex(0);
if (valueCount == 0) {
validityBuffer.writerIndex(0);
offsetBuffer.writerIndex(0);
valueBuffer.writerIndex(0);
} else {
final long lastDataOffset = getStartOffset(valueCount);
validityBuffer.writerIndex(BitVectorHelper.getValidityBufferSizeFromCount(valueCount));
offsetBuffer.writerIndex((long) (valueCount + 1) * OFFSET_WIDTH);
valueBuffer.writerIndex(lastDataOffset);
}
// IPC serializer will determine readable bytes based on `readerIndex` and `writerIndex`.
// Both are set to 0 means 0 bytes are written to the IPC stream which will crash IPC readers
// in other libraries. According to Arrow spec, we should still output the offset buffer which
// is [0].
final long requiredOffsetBufferSize = (long) (valueCount + 1) * OFFSET_WIDTH;
if (offsetBuffer.capacity() < requiredOffsetBufferSize) {
ArrowBuf newOffsetBuffer = allocateOffsetBuffer(requiredOffsetBufferSize);
if (offsetBuffer.capacity() > 0) {
newOffsetBuffer.setBytes(0, offsetBuffer, 0, offsetBuffer.capacity());
}
offsetBuffer.getReferenceManager().release();
offsetBuffer = newOffsetBuffer;
}
offsetBuffer.writerIndex(requiredOffsetBufferSize);
}

/** Same as {@link #allocateNewSafe()}. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,14 +389,26 @@ private void setReaderAndWriterIndex() {
valueBuffer.readerIndex(0);
if (valueCount == 0) {
validityBuffer.writerIndex(0);
offsetBuffer.writerIndex(0);
valueBuffer.writerIndex(0);
} else {
final int lastDataOffset = getStartOffset(valueCount);
validityBuffer.writerIndex(BitVectorHelper.getValidityBufferSizeFromCount(valueCount));
offsetBuffer.writerIndex((long) (valueCount + 1) * OFFSET_WIDTH);
valueBuffer.writerIndex(lastDataOffset);
}
// IPC serializer will determine readable bytes based on `readerIndex` and `writerIndex`.
// Both are set to 0 means 0 bytes are written to the IPC stream which will crash IPC readers
// in other libraries. According to Arrow spec, we should still output the offset buffer which
// is [0].
final long requiredOffsetBufferSize = (long) (valueCount + 1) * OFFSET_WIDTH;
if (offsetBuffer.capacity() < requiredOffsetBufferSize) {
ArrowBuf newOffsetBuffer = allocateOffsetBuffer(requiredOffsetBufferSize);
if (offsetBuffer.capacity() > 0) {
newOffsetBuffer.setBytes(0, offsetBuffer, 0, offsetBuffer.capacity());
}
offsetBuffer.getReferenceManager().release();
offsetBuffer = newOffsetBuffer;
}
offsetBuffer.writerIndex(requiredOffsetBufferSize);
}

/** Same as {@link #allocateNewSafe()}. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3940,4 +3940,42 @@ public void testVectorLoadUnloadOnNonVariadicVectors() {
}
}
}

@Test
public void testEmptyVarCharOffsetBuffer() {
// Validates that offset buffer has at least OFFSET_WIDTH bytes (for offset[0]=0)
// even when valueCount is 0, per Arrow specification.
try (VarCharVector vector = newVarCharVector("varchar", allocator)) {
vector.allocateNew();
vector.setValueCount(0);

List<ArrowBuf> buffers = vector.getFieldBuffers();
// buffers: [validity, offset, data]
assertTrue(
buffers.get(1).readableBytes() >= BaseVariableWidthVector.OFFSET_WIDTH,
"Offset buffer should have at least "
+ BaseVariableWidthVector.OFFSET_WIDTH
+ " bytes for offset[0]");
assertEquals(0, vector.getOffsetBuffer().getInt(0));
}
}

@Test
public void testEmptyLargeVarCharOffsetBuffer() {
// Validates that offset buffer has at least OFFSET_WIDTH bytes (for offset[0]=0)
// even when valueCount is 0, per Arrow specification.
try (LargeVarCharVector vector = new LargeVarCharVector("largevarchar", allocator)) {
vector.allocateNew();
vector.setValueCount(0);

List<ArrowBuf> buffers = vector.getFieldBuffers();
// buffers: [validity, offset, data]
assertTrue(
buffers.get(1).readableBytes() >= BaseLargeVariableWidthVector.OFFSET_WIDTH,
"Offset buffer should have at least "
+ BaseLargeVariableWidthVector.OFFSET_WIDTH
+ " bytes for offset[0]");
assertEquals(0, vector.getOffsetBuffer().getLong(0));
}
}
}
Loading