stevenzwu commented on code in PR #17434:
URL: https://github.com/apache/iceberg/pull/17434#discussion_r3708146056


##########
core/src/main/java/org/apache/iceberg/V4ManifestReader.java:
##########
@@ -146,6 +151,22 @@ private TrackedFile prepare(TrackedFile trackedFile) {
     return trackedFile;
   }
 
+  // resolves stored locations against the table location
+  private TrackedFile copyResolved(TrackedFile trackedFile) {
+    TrackedFileStruct copy = (TrackedFileStruct) trackedFile.copy();

Review Comment:
   > Requiring immutability results in a lot of object thrashing.
   
   @danielcweeks this doesn't require additional object copy/thrashing.
   
   Currently, we do `trackedFile.copy()` first, then adjust the location 
fields. What I suggested is also one copy 
`copyWithResolvedLocation(tableLocation)`.  There is no difference in terms of 
memory allocation.
   
   > I'm a bit wary of changing the semantics of the copy constructors to now 
do location resolution.
   
   To clarify: the copy constructor stays as a mechanical field installer — it 
takes the already-resolved values as parameters, not `tableLocation` itself. 
The resolution lives one layer up in a new `copyWithResolvedLocation(String 
tableLocation)` method that computes the resolved values and invokes the 
constructor:
   
   ```java
   // copy constructor: pure field installer, does not know about LocationUtil
   private TrackedFileStruct(
       TrackedFileStruct toCopy,
       Set<Integer> statsIds,
       String resolvedLocation,
       DeletionVector dvWithResolvedLocation) {
     super(toCopy);
     ...
     this.location = resolvedLocation;
     ...
     this.deletionVector = dvWithResolvedLocation;
     ...
   }
   
   // new caller-facing entry point that resolves before installing
   TrackedFile copyWithResolvedLocation(String tableLocation) {
     String resolvedLocation =
         location != null ? LocationUtil.resolveLocation(tableLocation, 
location) : null;
     return new TrackedFileStruct(
         this, null, resolvedLocation, resolveDvLocation(deletionVector, 
tableLocation));
   }
   
   private static DeletionVector resolveDvLocation(DeletionVector dv, String 
tableLocation) {
     return DeletionVectorStruct.builder()
         .location(LocationUtil.resolveLocation(tableLocation, dv.location()))
         .offset(dv.offset())
         .sizeInBytes(dv.sizeInBytes())
         .cardinality(dv.cardinality())
         .build();
   }
   ```
   
   `V4ManifestReader.copyResolved` then collapses to 
`trackedFile.copyWithResolvedLocation(tableLocation)`.
   
   > a third option: NOT do location resolution in this layer, and instead do 
it lazily in scan planning time, in the adapter layer in the respective 
`path()` methods
   
   I like the location resolution in this layer. A single place. We can do the 
same thing on the write direction like `V4ManifestWriter`.
   
   > the objects are not immutable btw since they expose positional setters 
anyway
   
   Agree they are not immutable. But the positional setter is a framework hook 
for the Avro/Parquet reader to populate fields by ordinal during 
deserialization — a construction-time protocol, not a post-construction 
mutation API. A named `void setLocation(String)` looks like a domain-level 
"mutate this specific field" method that any package member could call. The 
concern is probably more on the API shape. 
   
   But since these are non-public setters, I am ok with it. 
`BaseFile.setManifestLocation` is a similar pattern.
   



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to