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 4c760fe85a [flink] Fix lookup output projection with internal key 
fields (#9392)
4c760fe85a is described below

commit 4c760fe85a549a9217020f2b946085a71d7cc15b
Author: YeJunHao <[email protected]>
AuthorDate: Wed Aug 26 14:52:07 2026 +0800

    [flink] Fix lookup output projection with internal key fields (#9392)
---
 .../flink/lookup/FileStoreLookupFunction.java      | 19 +++++++++++---
 .../org/apache/paimon/flink/LookupJoinITCase.java  | 30 ++++++++++++++++++++++
 .../flink/lookup/FileStoreLookupFunctionTest.java  | 13 +++++++---
 3 files changed, 56 insertions(+), 6 deletions(-)

diff --git 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/lookup/FileStoreLookupFunction.java
 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/lookup/FileStoreLookupFunction.java
index aa647f167c..762b0dd3ee 100644
--- 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/lookup/FileStoreLookupFunction.java
+++ 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/lookup/FileStoreLookupFunction.java
@@ -27,6 +27,7 @@ import 
org.apache.paimon.flink.FlinkConnectorOptions.LookupCacheMode;
 import org.apache.paimon.flink.FlinkRowData;
 import org.apache.paimon.flink.FlinkRowDataWithBlob;
 import org.apache.paimon.flink.FlinkRowWrapper;
+import org.apache.paimon.flink.ProjectedRowData;
 import org.apache.paimon.flink.lookup.partitioner.ShuffleStrategy;
 import org.apache.paimon.flink.metrics.FlinkMetricRegistry;
 import org.apache.paimon.flink.utils.RuntimeContextUtils;
@@ -94,6 +95,9 @@ public class FileStoreLookupFunction implements Serializable, 
Closeable {
     private final FileStoreTable table;
     @Nullable private final PartitionLoader partitionLoader;
     private final List<String> projectFields;
+    /** Projects rows with internal lookup fields back to the fields requested 
by Flink. */
+    @Nullable private final int[] outputProjection;
+
     private final List<String> joinKeys;
     @Nullable private final Predicate predicate;
     @Nullable private final RefreshBlacklist refreshBlacklist;
@@ -143,10 +147,11 @@ public class FileStoreLookupFunction implements 
Serializable, Closeable {
                         .mapToObj(i -> 
rowType.getFieldNames().get(projection[i]))
                         .collect(Collectors.toList());
 
-        this.projectFields =
+        List<String> outputFields =
                 Arrays.stream(projection)
                         .mapToObj(i -> rowType.getFieldNames().get(i))
                         .collect(Collectors.toList());
+        this.projectFields = new ArrayList<>(outputFields);
 
         // add primary keys
         for (String field : table.primaryKeys()) {
@@ -158,6 +163,10 @@ public class FileStoreLookupFunction implements 
Serializable, Closeable {
         if (partitionLoader != null) {
             partitionLoader.addPartitionKeysTo(joinKeys, projectFields);
         }
+        this.outputProjection =
+                outputFields.equals(projectFields)
+                        ? null
+                        : 
outputFields.stream().mapToInt(projectFields::indexOf).toArray();
         RowType projectedType = rowType.project(projectFields);
         this.projectFieldsGetters =
                 IntStream.range(0, projectedType.getFieldCount())
@@ -359,10 +368,14 @@ public class FileStoreLookupFunction implements 
Serializable, Closeable {
         List<RowData> rows = new ArrayList<>();
         List<InternalRow> lookupResults = lookupTable.get(key);
         for (InternalRow matchedRow : lookupResults) {
-            rows.add(
+            RowData rowData =
                     blobFields.isEmpty()
                             ? new FlinkRowData(matchedRow)
-                            : new FlinkRowDataWithBlob(matchedRow, blobFields, 
blobAsDescriptor));
+                            : new FlinkRowDataWithBlob(matchedRow, blobFields, 
blobAsDescriptor);
+            rows.add(
+                    outputProjection == null
+                            ? rowData
+                            : 
ProjectedRowData.from(outputProjection).replaceRow(rowData));
         }
 
         if (LOG.isDebugEnabled()) {
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/LookupJoinITCase.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/LookupJoinITCase.java
index 385d1d1cf6..fe522d765c 100644
--- 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/LookupJoinITCase.java
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/LookupJoinITCase.java
@@ -302,6 +302,36 @@ public class LookupJoinITCase extends CatalogITCaseBase {
         iterator.close();
     }
 
+    @ParameterizedTest
+    @ValueSource(booleans = {false, true})
+    public void testAsyncLookupWithDynamicPartitionProjection(boolean 
primaryKey) throws Exception {
+        sql(
+                "CREATE TABLE ASYNC_DIM (i INT, j INT, dt STRING%s) "
+                        + "PARTITIONED BY (`dt`) WITH ("
+                        + "'lookup.cache' = 'memory', "
+                        + "'continuous.discovery-interval' = '1 ms')",
+                primaryKey ? ", PRIMARY KEY (dt, i, j) NOT ENFORCED" : "");
+        sql(
+                "INSERT INTO ASYNC_DIM VALUES "
+                        + "(1, 11, '2026-08-25'), "
+                        + "(1, 12, '2026-08-25'), "
+                        + "(2, 21, '2026-08-25')");
+
+        String query =
+                "SELECT T.i, D.j FROM T LEFT JOIN ASYNC_DIM "
+                        + "/*+ OPTIONS("
+                        + "'scan.partitions' = 'max_pt()', "
+                        + "'lookup.dynamic-partition.refresh-interval' = '1 
ms', "
+                        + "'lookup.async' = 'true') */ "
+                        + "FOR SYSTEM_TIME AS OF T.proctime AS D ON T.i = D.i";
+        BlockingIterator<Row, Row> iterator = 
BlockingIterator.of(sEnv.executeSql(query).collect());
+
+        sql("INSERT INTO T VALUES (1), (2)");
+        assertThat(iterator.collect(3))
+                .containsExactlyInAnyOrder(Row.of(1, 11), Row.of(1, 12), 
Row.of(2, 21));
+        iterator.close();
+    }
+
     @Test
     public void testLookupMaxPtDynamicBucketTable() throws Exception {
         sql(
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/lookup/FileStoreLookupFunctionTest.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/lookup/FileStoreLookupFunctionTest.java
index 2db4d2f3be..4b3979b743 100644
--- 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/lookup/FileStoreLookupFunctionTest.java
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/lookup/FileStoreLookupFunctionTest.java
@@ -404,7 +404,7 @@ public class FileStoreLookupFunctionTest {
     }
 
     @Test
-    public void testDebugLogRowsWithAppendedPrimaryKey() throws Exception {
+    public void testLookupProjectionWithAppendedPrimaryKey() throws Exception {
         table = createStringFileStoreTable();
         lookupFunction =
                 new FileStoreLookupFunction(table, new int[] {2, 1}, new int[] 
{1}, null, null);
@@ -419,8 +419,15 @@ public class FileStoreLookupFunctionTest {
 
         Appender appender = addLookupFunctionAppender(Level.INFO);
         try {
-            lookupFunction.lookup(
-                    new 
FlinkRowData(GenericRow.of(BinaryString.fromString("key-1"))));
+            List<RowData> rows =
+                    new ArrayList<>(
+                            lookupFunction.lookup(
+                                    new FlinkRowData(
+                                            
GenericRow.of(BinaryString.fromString("key-1")))));
+            assertThat(rows).hasSize(1);
+            assertThat(rows.get(0).getArity()).isEqualTo(2);
+            
assertThat(rows.get(0).getString(0).toString()).isEqualTo("value-1");
+            assertThat(rows.get(0).getString(1).toString()).isEqualTo("key-1");
             assertThat(((CollectingAppender) appender).messages)
                     .noneMatch(message -> message.contains("matched rows in 
lookup table"));
         } finally {

Reply via email to