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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ All notable changes to this project will be documented in this file.
- nifi: Bump Hazelcast to `5.7.0` (partial backport of [NIFI-15942](https://issues.apache.org/jira/browse/NIFI-15942)) to fix CVE-2026-107726, for `2.6.0` and `2.9.0` ([#1737]).
- superset: Bump brotli to `1.2.1` to fix CVE-2026-111497 ([#1737]).
- hbase: Add `hadoop-azure` to the HBase `lib` directory again, so that `abfs://` works. This regressed in 26.7.0 with [#1511] ([#1731]).
- trino: Backport [trinodb/trino#26806](https://github.com/trinodb/trino/pull/26806) to `477` to fix `appendPositions` on `RowBlockBuilder` ignoring the offset ([#1738]).

### Removed

Expand Down Expand Up @@ -203,6 +204,7 @@ All notable changes to this project will be documented in this file.
[#1732]: https://github.com/stackabletech/docker-images/pull/1732
[#1735]: https://github.com/stackabletech/docker-images/pull/1735
[#1737]: https://github.com/stackabletech/docker-images/pull/1737
[#1738]: https://github.com/stackabletech/docker-images/pull/1738

## [26.7.0] - 2026-07-21

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
From 9d95866bf8e9e05416ee878923308f143dbd128e Mon Sep 17 00:00:00 2001
From: Razvan-Daniel Mihai <84674+razvan@users.noreply.github.com>
Date: Mon, 9 Nov 2026 10:19:25 +0100
Subject: Fix an issue on appendPositions on RowBlockBuilder

This is a backport of https://github.com/trinodb/trino/pull/26806
---
.../io/trino/spi/block/RowBlockBuilder.java | 2 +-
.../spi/block/AbstractTestBlockBuilder.java | 220 ++++++++++--------
2 files changed, 122 insertions(+), 100 deletions(-)

diff --git a/core/trino-spi/src/main/java/io/trino/spi/block/RowBlockBuilder.java b/core/trino-spi/src/main/java/io/trino/spi/block/RowBlockBuilder.java
index b7c4f88068..acdb2d4b06 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/block/RowBlockBuilder.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/block/RowBlockBuilder.java
@@ -276,7 +276,7 @@ public class RowBlockBuilder

if (startOffset == 0) {
for (int fieldId = 0; fieldId < fieldBlockBuilders.length; fieldId++) {
- appendPositionsToField(rawFieldBlocks[fieldId], positions, 0, length, fieldBlockBuilders[fieldId]);
+ appendPositionsToField(rawFieldBlocks[fieldId], positions, offset, length, fieldBlockBuilders[fieldId]);
}
}
else {
diff --git a/core/trino-spi/src/test/java/io/trino/spi/block/AbstractTestBlockBuilder.java b/core/trino-spi/src/test/java/io/trino/spi/block/AbstractTestBlockBuilder.java
index ceca56bae0..28ec61b07c 100644
--- a/core/trino-spi/src/test/java/io/trino/spi/block/AbstractTestBlockBuilder.java
+++ b/core/trino-spi/src/test/java/io/trino/spi/block/AbstractTestBlockBuilder.java
@@ -24,6 +24,8 @@ import static org.assertj.core.api.Assertions.assertThat;

public abstract class AbstractTestBlockBuilder<T>
{
+ private static final int[] OFFSETS = new int[] {0, 2};
+
protected abstract BlockBuilder createBlockBuilder();

protected abstract List<T> getTestValues();
@@ -52,197 +54,216 @@ public abstract class AbstractTestBlockBuilder<T>
public void testAppend()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlock(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlock(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.append(inputValues, 1);
- blockBuilder.append(inputValues, 3);
- blockBuilder.append(inputValues, 1);
- blockBuilder.append(inputValues, 3);
- ValueBlock valueBlock = blockBuilder.buildValueBlock();
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.append(inputValues, 1);
+ blockBuilder.append(inputValues, 3);
+ blockBuilder.append(inputValues, 1);
+ blockBuilder.append(inputValues, 3);
+ ValueBlock valueBlock = blockBuilder.buildValueBlock();

- assertThat(valueBlock.mayHaveNull()).isFalse();
+ assertThat(valueBlock.mayHaveNull()).isFalse();

- List<T> actualValues = blockToValues(valueBlock);
- assertThat(actualValues).containsExactly(values.get(1), values.get(3), values.get(1), values.get(3));
+ List<T> actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).containsExactly(values.get(1), values.get(3), values.get(1), values.get(3));
+ }
}

@Test
public void testAppendWithNulls()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlockWithOddPositionsNull(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlockWithOddPositionsNull(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.append(inputValues, 1);
- blockBuilder.append(inputValues, 3);
- ValueBlock valueBlock = blockBuilder.buildValueBlock();
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.append(inputValues, 1);
+ blockBuilder.append(inputValues, 3);
+ ValueBlock valueBlock = blockBuilder.buildValueBlock();

- assertThat(valueBlock.mayHaveNull()).isTrue();
+ assertThat(valueBlock.mayHaveNull()).isTrue();

- List<T> actualValues = blockToValues(valueBlock);
- assertThat(actualValues).hasSize(2).containsOnlyNulls();
+ List<T> actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).hasSize(2).containsOnlyNulls();

- // add a non-null value
- blockBuilder.append(inputValues, 2);
- valueBlock = blockBuilder.buildValueBlock();
+ // add a non-null value
+ blockBuilder.append(inputValues, 2);
+ valueBlock = blockBuilder.buildValueBlock();

- actualValues = blockToValues(valueBlock);
- assertThat(actualValues).containsExactly(null, null, values.get(2));
+ actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).containsExactly(null, null, values.get(2));
+ }
}

@Test
public void testAppendRepeated()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlock(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlock(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.appendRepeated(inputValues, 1, 10);
- blockBuilder.appendRepeated(inputValues, 3, 10);
- ValueBlock valueBlock = blockBuilder.buildValueBlock();
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.appendRepeated(inputValues, 1, 10);
+ blockBuilder.appendRepeated(inputValues, 3, 10);
+ ValueBlock valueBlock = blockBuilder.buildValueBlock();

- assertThat(valueBlock.mayHaveNull()).isFalse();
+ assertThat(valueBlock.mayHaveNull()).isFalse();

- List<T> actualValues = blockToValues(valueBlock);
- assertThat(actualValues).containsExactlyElementsOf(Iterables.concat(nCopies(10, values.get(1)), nCopies(10, values.get(3))));
+ List<T> actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).containsExactlyElementsOf(Iterables.concat(nCopies(10, values.get(1)), nCopies(10, values.get(3))));
+ }
}

@Test
public void testAppendRepeatedWithNulls()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlockWithOddPositionsNull(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlockWithOddPositionsNull(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.appendRepeated(inputValues, 1, 10);
- blockBuilder.appendRepeated(inputValues, 3, 10);
- ValueBlock valueBlock = blockBuilder.buildValueBlock();
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.appendRepeated(inputValues, 1, 10);
+ blockBuilder.appendRepeated(inputValues, 3, 10);
+ ValueBlock valueBlock = blockBuilder.buildValueBlock();

- assertThat(valueBlock.mayHaveNull()).isTrue();
+ assertThat(valueBlock.mayHaveNull()).isTrue();

- List<T> actualValues = blockToValues(valueBlock);
- assertThat(actualValues).hasSize(20).containsOnlyNulls();
+ List<T> actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).hasSize(20).containsOnlyNulls();

- // an all-null block should be converted to a RunLengthEncodedBlock
- assertThat(blockBuilder.build()).isInstanceOf(RunLengthEncodedBlock.class);
+ // an all-null block should be converted to a RunLengthEncodedBlock
+ assertThat(blockBuilder.build()).isInstanceOf(RunLengthEncodedBlock.class);

- // add some non-null values
- blockBuilder.appendRepeated(inputValues, 2, 10);
- valueBlock = blockBuilder.buildValueBlock();
+ // add some non-null values
+ blockBuilder.appendRepeated(inputValues, 2, 10);
+ valueBlock = blockBuilder.buildValueBlock();

- actualValues = blockToValues(valueBlock);
- assertThat(actualValues).containsExactlyElementsOf(Iterables.concat(nCopies(20, null), nCopies(10, values.get(2))));
+ actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).containsExactlyElementsOf(Iterables.concat(nCopies(20, null), nCopies(10, values.get(2))));
+ }
}

@Test
public void testAppendRange()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlock(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlock(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.appendRange(inputValues, 1, 3);
- blockBuilder.appendRange(inputValues, 2, 3);
- ValueBlock valueBlock = blockBuilder.buildValueBlock();
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.appendRange(inputValues, 1, 3);
+ blockBuilder.appendRange(inputValues, 2, 3);
+ ValueBlock valueBlock = blockBuilder.buildValueBlock();

- assertThat(valueBlock.mayHaveNull()).isFalse();
+ assertThat(valueBlock.mayHaveNull()).isFalse();

- List<T> actualValues = blockToValues(valueBlock);
- assertThat(actualValues).containsExactlyElementsOf(Iterables.concat(values.subList(1, 4), values.subList(2, 5)));
+ List<T> actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).containsExactlyElementsOf(Iterables.concat(values.subList(1, 4), values.subList(2, 5)));
+ }
}

@Test
public void testAppendRangeWithNulls()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlockWithOddPositionsNull(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlockWithOddPositionsNull(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.appendRange(inputValues, 1, 3);
- blockBuilder.appendRange(inputValues, 2, 3);
- ValueBlock valueBlock = blockBuilder.buildValueBlock();
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.appendRange(inputValues, 1, 3);
+ blockBuilder.appendRange(inputValues, 2, 3);
+ ValueBlock valueBlock = blockBuilder.buildValueBlock();

- assertThat(valueBlock.mayHaveNull()).isTrue();
+ assertThat(valueBlock.mayHaveNull()).isTrue();

- List<T> actualValues = blockToValues(valueBlock);
- assertThat(actualValues).containsExactly(null, values.get(2), null, values.get(2), null, values.get(4));
+ List<T> actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).containsExactly(null, values.get(2), null, values.get(2), null, values.get(4));
+ }
}

@Test
public void testAppendPositions()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlock(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlock(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.appendPositions(inputValues, new int[] {-100, 1, 3, 2, -100}, 1, 3);
- blockBuilder.appendPositions(inputValues, new int[] {-100, 4, 0, -100}, 1, 2);
- ValueBlock valueBlock = blockBuilder.buildValueBlock();
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.appendPositions(inputValues, new int[] {-100, 1, 3, 2, -100}, 1, 3);
+ blockBuilder.appendPositions(inputValues, new int[] {-100, 4, 0, -100}, 1, 2);
+ ValueBlock valueBlock = blockBuilder.buildValueBlock();

- assertThat(valueBlock.mayHaveNull()).isFalse();
+ assertThat(valueBlock.mayHaveNull()).isFalse();

- List<T> actualValues = blockToValues(valueBlock);
- assertThat(actualValues).containsExactly(values.get(1), values.get(3), values.get(2), values.get(4), values.get(0));
+ List<T> actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).containsExactly(values.get(1), values.get(3), values.get(2), values.get(4), values.get(0));
+ }
}

@Test
public void testAppendPositionsWithNull()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlockWithOddPositionsNull(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlockWithOddPositionsNull(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.appendPositions(inputValues, new int[] {-100, 1, 3, 2, -100}, 1, 3);
- blockBuilder.appendPositions(inputValues, new int[] {-100, 4, 0, -100}, 1, 2);
- ValueBlock valueBlock = blockBuilder.buildValueBlock();
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.appendPositions(inputValues, new int[] {-100, 1, 3, 2, -100}, 1, 3);
+ blockBuilder.appendPositions(inputValues, new int[] {-100, 4, 0, -100}, 1, 2);
+ ValueBlock valueBlock = blockBuilder.buildValueBlock();

- assertThat(valueBlock.mayHaveNull()).isTrue();
+ assertThat(valueBlock.mayHaveNull()).isTrue();

- List<T> actualValues = blockToValues(valueBlock);
- assertThat(actualValues).containsExactly(null, null, values.get(2), values.get(4), values.get(0));
+ List<T> actualValues = blockToValues(valueBlock);
+ assertThat(actualValues).containsExactly(null, null, values.get(2), values.get(4), values.get(0));
+ }
}

@Test
public void testResetTo()
{
List<T> values = getTestValues();
- ValueBlock inputValues = createOffsetBlock(values);
+ for (int offset : OFFSETS) {
+ ValueBlock inputValues = createOffsetBlock(values, offset);

- BlockBuilder blockBuilder = createBlockBuilder();
- blockBuilder.appendRange(inputValues, 0, inputValues.getPositionCount());
- assertThat(blockToValues(blockBuilder.buildValueBlock())).containsExactlyElementsOf(values);
+ BlockBuilder blockBuilder = createBlockBuilder();
+ blockBuilder.appendRange(inputValues, 0, inputValues.getPositionCount());
+ assertThat(blockToValues(blockBuilder.buildValueBlock())).containsExactlyElementsOf(values);

- blockBuilder.resetTo(4);
- assertThat(blockToValues(blockBuilder.buildValueBlock())).containsExactlyElementsOf(values.subList(0, 4));
+ blockBuilder.resetTo(4);
+ assertThat(blockToValues(blockBuilder.buildValueBlock())).containsExactlyElementsOf(values.subList(0, 4));

- blockBuilder.appendRange(inputValues, 0, inputValues.getPositionCount());
- assertThat(blockToValues(blockBuilder.buildValueBlock())).containsExactlyElementsOf(Iterables.concat(values.subList(0, 4), values));
+ blockBuilder.appendRange(inputValues, 0, inputValues.getPositionCount());
+ assertThat(blockToValues(blockBuilder.buildValueBlock())).containsExactlyElementsOf(Iterables.concat(values.subList(0, 4), values));

- blockBuilder.resetTo(0);
- assertThat(blockToValues(blockBuilder.buildValueBlock())).isEmpty();
+ blockBuilder.resetTo(0);
+ assertThat(blockToValues(blockBuilder.buildValueBlock())).isEmpty();

- blockBuilder.appendRange(inputValues, 0, inputValues.getPositionCount());
- assertThat(blockToValues(blockBuilder.buildValueBlock())).containsExactlyElementsOf(values);
+ blockBuilder.appendRange(inputValues, 0, inputValues.getPositionCount());
+ assertThat(blockToValues(blockBuilder.buildValueBlock())).containsExactlyElementsOf(values);
+ }
}

/**
* Create a block that is offset from the start of the underlying array
*/
- private ValueBlock createOffsetBlock(List<T> values)
+ private ValueBlock createOffsetBlock(List<T> values, int offset)
{
- return blockFromValues(Iterables.concat(nCopies(2, getUnusedTestValue()), values, nCopies(2, getUnusedTestValue())))
- .getRegion(2, values.size());
+ return blockFromValues(Iterables.concat(nCopies(offset, getUnusedTestValue()), values, nCopies(offset, getUnusedTestValue())))
+ .getRegion(offset, values.size());
}

/**
* Create a block that is offset from the start of the underlying array
*/
- private ValueBlock createOffsetBlockWithOddPositionsNull(List<T> values)
+ private ValueBlock createOffsetBlockWithOddPositionsNull(List<T> values, int offset)
{
ArrayList<T> blockValues = new ArrayList<>();
- blockValues.add(getUnusedTestValue());
- blockValues.add(getUnusedTestValue());
+ for (int i = 0; i < offset; i++) {
+ blockValues.add(getUnusedTestValue());
+ }
for (int i = 0; i < values.size(); i++) {
T value = values.get(i);
if (i % 2 == 0) {
@@ -252,8 +273,9 @@ public abstract class AbstractTestBlockBuilder<T>
blockValues.add(null);
}
}
- blockValues.add(getUnusedTestValue());
- blockValues.add(getUnusedTestValue());
- return blockFromValues(blockValues).getRegion(2, values.size());
+ for (int i = 0; i < offset; i++) {
+ blockValues.add(getUnusedTestValue());
+ }
+ return blockFromValues(blockValues).getRegion(offset, values.size());
}
}
Loading