LuciferYang commented on code in PR #9966:
URL: https://github.com/apache/paimon/pull/9966#discussion_r4105624934


##########
paimon-core/src/main/java/org/apache/paimon/operation/DataEvolutionFileStoreScan.java:
##########
@@ -290,6 +318,35 @@ static List<ManifestEntry> pruneByReadType(
                 : kept;
     }
 
+    /**
+     * Whether the row-id ranges of {@code entries} together cover every 
{@code target} range
+     * (inclusive), with no gap. Dedicated files are always within the group's 
full range, so
+     * covering the requested targets means the reader can derive the range 
from them without the
+     * anchor.
+     */
+    private static boolean coversRanges(List<ManifestEntry> entries, 
List<Range> targets) {

Review Comment:
   Fixed. Coverage is now judged per projected column instead of by unioning 
files across columns, so a projection whose columns cover disjoint sub-ranges 
(b1 over [0,6], b2 over [3,9]) keeps the anchor. Added 
`DataEvolutionFileStoreScanTest#testReadTypePruningKeepsAnchorForMultiColumnBlobs`.



##########
paimon-core/src/main/java/org/apache/paimon/operation/DataEvolutionFileStoreScan.java:
##########
@@ -281,6 +286,29 @@ static List<ManifestEntry> pruneByReadType(
         if (anchor != null && !kept.contains(anchor)) {
             kept.add(anchor);
         }
+        // Blob and vector-store files may each cover only a sub-range of 
their group. If the kept
+        // files are all dedicated files that together do not cover the 
requested rows (the whole
+        // group when there is no row-range pushdown), the reader would derive 
the range from those
+        // sub-ranges and drop the rows outside them, so keep the full-range 
anchor. When they
+        // already cover the requested rows, the anchor is unnecessary and 
would only read an extra
+        // file.
+        if (anchor == null
+                && !kept.isEmpty()
+                && kept.stream()
+                        .allMatch(
+                                e ->
+                                        isBlobFile(e.file().fileName())
+                                                || 
isVectorStoreFile(e.file().fileName()))) {
+            ManifestEntry fullRangeAnchor = retrieveAnchorFile(group, 
ManifestEntry::file);
+            Range fullRange = fullRangeAnchor.file().nonNullRowIdRange();
+            List<Range> requested =
+                    rowRangeIndex == null
+                            ? Collections.singletonList(fullRange)
+                            : rowRangeIndex.intersectedRanges(fullRange.from, 
fullRange.to);
+            if (!coversRanges(kept, requested)) {
+                kept.add(fullRangeAnchor);

Review Comment:
   Fixed. `DataEvolutionVectorReadPlanner` now plans explicit ranges when a 
projected vector store covers only a sub-range of its group, so the uncovered 
rows are NULL-filled through the range-aware path instead of falling to the 
sequential reader that rejects the mismatched row count. Added 
`VectorStoreTableTest#testPartialUpdateWithMissingVectorRangeWithoutDeletionVectors`
 (no deletion vectors).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to