This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new dfaf2f2fb7 [core] Preserve query authorization when wrapping data
evolution index splits (#9925)
dfaf2f2fb7 is described below
commit dfaf2f2fb7e9c50b5efa46514f85e5107ee1f777
Author: YeJunHao <[email protected]>
AuthorDate: Thu Sep 17 18:24:50 2026 +0800
[core] Preserve query authorization when wrapping data evolution index
splits (#9925)
---
.../paimon/globalindex/DataEvolutionBatchScan.java | 23 +++++---
.../globalindex/DataEvolutionBatchScanTest.java | 68 ++++++++++++++++++++++
2 files changed, 83 insertions(+), 8 deletions(-)
diff --git
a/paimon-core/src/main/java/org/apache/paimon/globalindex/DataEvolutionBatchScan.java
b/paimon-core/src/main/java/org/apache/paimon/globalindex/DataEvolutionBatchScan.java
index e412d8123f..618a0ee765 100644
---
a/paimon-core/src/main/java/org/apache/paimon/globalindex/DataEvolutionBatchScan.java
+++
b/paimon-core/src/main/java/org/apache/paimon/globalindex/DataEvolutionBatchScan.java
@@ -37,6 +37,7 @@ import org.apache.paimon.table.source.AppendBatchTableScan;
import org.apache.paimon.table.source.DataSplit;
import org.apache.paimon.table.source.DataTableScan;
import org.apache.paimon.table.source.InnerTableScan;
+import org.apache.paimon.table.source.QueryAuthSplit;
import org.apache.paimon.table.source.Split;
import org.apache.paimon.types.RowType;
import org.apache.paimon.utils.Filter;
@@ -455,18 +456,24 @@ public class DataEvolutionBatchScan implements
DataTableScan {
public static Plan wrapToIndexSplits(
List<Split> splits, RowRangeIndex rowRangeIndex, ScoreGetter
scoreGetter) {
List<Split> indexedSplits = new ArrayList<>();
- Function<Split, List<IndexedSplit>> process =
- split ->
- Collections.singletonList(
- split instanceof IndexedSplit
- ? (IndexedSplit) split
- : wrap((DataSplit) split,
rowRangeIndex, scoreGetter));
+ Function<Split, List<Split>> process =
+ split -> Collections.singletonList(wrap(split, rowRangeIndex,
scoreGetter));
randomlyExecuteSequentialReturn(process, splits,
null).forEachRemaining(indexedSplits::add);
return () -> indexedSplits;
}
- private static IndexedSplit wrap(
- DataSplit dataSplit, final RowRangeIndex rowRangeIndex,
ScoreGetter scoreGetter) {
+ private static Split wrap(
+ Split split, final RowRangeIndex rowRangeIndex, ScoreGetter
scoreGetter) {
+ if (split instanceof QueryAuthSplit) {
+ QueryAuthSplit authSplit = (QueryAuthSplit) split;
+ return new QueryAuthSplit(
+ wrap(authSplit.split(), rowRangeIndex, scoreGetter),
authSplit.authResult());
+ }
+ if (split instanceof IndexedSplit) {
+ return split;
+ }
+
+ DataSplit dataSplit = (DataSplit) split;
List<DataFileMeta> files = dataSplit.dataFiles();
List<Range> expected = new ArrayList<>();
diff --git
a/paimon-core/src/test/java/org/apache/paimon/globalindex/DataEvolutionBatchScanTest.java
b/paimon-core/src/test/java/org/apache/paimon/globalindex/DataEvolutionBatchScanTest.java
index 78771719d0..8ec43fe004 100644
---
a/paimon-core/src/test/java/org/apache/paimon/globalindex/DataEvolutionBatchScanTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/globalindex/DataEvolutionBatchScanTest.java
@@ -18,6 +18,7 @@
package org.apache.paimon.globalindex;
+import org.apache.paimon.catalog.TableQueryAuthResult;
import org.apache.paimon.data.BinaryRow;
import org.apache.paimon.io.DataFileMeta;
import org.apache.paimon.predicate.Predicate;
@@ -25,6 +26,7 @@ import org.apache.paimon.predicate.PredicateBuilder;
import org.apache.paimon.table.source.AppendBatchTableScan;
import org.apache.paimon.table.source.DataSplit;
import org.apache.paimon.table.source.DataTableScan;
+import org.apache.paimon.table.source.QueryAuthSplit;
import org.apache.paimon.table.source.Split;
import org.apache.paimon.table.source.snapshot.SnapshotReader;
import org.apache.paimon.types.DataField;
@@ -34,6 +36,8 @@ import org.apache.paimon.utils.Range;
import org.apache.paimon.utils.RowRangeIndex;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
@@ -210,6 +214,70 @@ public class DataEvolutionBatchScanTest {
.containsExactly(new Range(4200, 4450), new Range(4650, 4700));
}
+ @ParameterizedTest
+ @ValueSource(booleans = {false, true})
+ public void testWrapToIndexSplitsWithQueryAuth(boolean hasAuthResult) {
+ DataSplit split =
+ DataSplit.builder()
+ .withSnapshot(1L)
+ .withPartition(BinaryRow.EMPTY_ROW)
+ .withBucket(0)
+ .withBucketPath("bucket-0")
+
.withDataFiles(Collections.singletonList(newAppendFile(0L, 10L, "file-0")))
+ .build();
+ TableQueryAuthResult authResult =
+ hasAuthResult
+ ? new TableQueryAuthResult(
+ Collections.singletonList("filter-json"),
+ Collections.singletonMap("f0", "mask-json"))
+ : null;
+ QueryAuthSplit authSplit = new QueryAuthSplit(split, authResult);
+
+ List<Split> indexedSplits =
+ DataEvolutionBatchScan.wrapToIndexSplits(
+ Collections.singletonList(authSplit),
+ RowRangeIndex.create(
+ Arrays.asList(new Range(1, 2), new
Range(7, 12))),
+ rowId -> rowId + 0.5f)
+ .splits();
+
+ assertThat(indexedSplits).hasSize(1);
+ assertThat(indexedSplits.get(0)).isInstanceOf(QueryAuthSplit.class);
+ QueryAuthSplit indexedAuthSplit = (QueryAuthSplit)
indexedSplits.get(0);
+ assertThat(indexedAuthSplit.authResult()).isSameAs(authResult);
+ assertThat(indexedAuthSplit.split()).isInstanceOf(IndexedSplit.class);
+ IndexedSplit indexedSplit = (IndexedSplit) indexedAuthSplit.split();
+ assertThat(indexedSplit.dataSplit()).isSameAs(split);
+ assertThat(indexedSplit.rowRanges()).containsExactly(new Range(1, 2),
new Range(7, 9));
+ assertThat(indexedSplit.scores()).containsExactly(1.5f, 2.5f, 7.5f,
8.5f, 9.5f);
+ assertThat(authSplit.split()).isSameAs(split);
+ }
+
+ @Test
+ public void testWrapToIndexSplitsKeepsExistingIndexedSplits() {
+ IndexedSplit indexedSplit =
+ new IndexedSplit(
+ mock(DataSplit.class),
+ Collections.singletonList(new Range(1, 2)),
+ new float[] {1.5f, 2.5f});
+ TableQueryAuthResult authResult = mock(TableQueryAuthResult.class);
+
+ List<Split> indexedSplits =
+ DataEvolutionBatchScan.wrapToIndexSplits(
+ Arrays.asList(
+ indexedSplit, new
QueryAuthSplit(indexedSplit, authResult)),
+ null,
+ null)
+ .splits();
+
+ assertThat(indexedSplits).hasSize(2);
+ assertThat(indexedSplits.get(0)).isSameAs(indexedSplit);
+ assertThat(indexedSplits.get(1)).isInstanceOf(QueryAuthSplit.class);
+ QueryAuthSplit indexedAuthSplit = (QueryAuthSplit)
indexedSplits.get(1);
+ assertThat(indexedAuthSplit.authResult()).isSameAs(authResult);
+ assertThat(indexedAuthSplit.split()).isSameAs(indexedSplit);
+ }
+
private static RowType rowTypeWithRowId() {
return RowType.of(
new DataField(0, "f0", DataTypes.INT()),