twmb commented on PR #890:
URL: https://github.com/apache/iceberg-go/pull/890#issuecomment-4246697937

   twmb/avro supports aliases on decode as well, usable via schema resolution. 
The arg ordering is different in my Resolve (though in research mine matches 
the ecosystem more broadly).
   
   One "downside", maybe (it's more spec correct but less lenient), of my repo 
vs. hamba is that twmb/avro is stricter when decoding writer-schema record 
fields that are missing from the struct being decoded into (reader-schema) - 
twmb/avro will error when trying to decode `added_data_files_count` into a 
struct that doesn't have that field (i.e. the silent bug that this PR is about).
   
   The complication with the approach proposed in the comment above is that we 
need to read the ocf header to know what schema to use / what struct to decode 
into, but the existing `ocf.WithReaderSchema` needs the reader schema up front 
(hamba/avro has the same limitation), which means the cleanest wiring needs 
either a buffer-and-reopen dance or a new API in twmb/avro.
   
   So, I'm adding `WithReaderSchemaFunc` option to twmb/avro's ocf package (to 
be released as 1.6.0 imminently, hopefully the last minor release for a while 
...). The callback is invoked after the ocf header has been parsed: 
`rd.Schema()` returns the writer schema, `rd.Metadata()` is populated, and 
whatever schema it returns becomes the reader schema for resolution.
   
   With that option, `ReadManifestList` becomes something like:
   
   ```go
   type manifestFileV1 struct {
       // ...
       AddedFilesCount    *int32 
`avro:"added_files_count,alias=added_data_files_count"`
       ExistingFilesCount *int32 
`avro:"existing_files_count,alias=existing_data_files_count"`
       DeletedFilesCount  *int32 
`avro:"deleted_files_count,alias=deleted_data_files_count"`
       // ...
   }
   
   type manifestFile struct {
       // ...
       AddedFilesCount    int32 
`avro:"added_files_count,alias=added_data_files_count"`
       ExistingFilesCount int32 
`avro:"existing_files_count,alias=existing_data_files_count"`
       DeletedFilesCount  int32 
`avro:"deleted_files_count,alias=deleted_data_files_count"`
       // ...
   }
   
   var (
       manifestFileV1Reader = avro.MustSchemaFor[manifestFileV1]()
       manifestFileReader   = avro.MustSchemaFor[manifestFile]()
   )
   
   func ReadManifestList(in io.Reader) ([]ManifestFile, error) {
       var version int
   
       rd, err := ocf.NewReader(in, ocf.WithReaderSchemaFunc(func(rd 
*ocf.Reader) (*avro.Schema, error) {
           version = 1
           if raw := rd.Metadata()["format-version"]; len(raw) > 0 {
               v, err := strconv.Atoi(string(raw))
               if err != nil {
                   return nil, fmt.Errorf("invalid format-version: %w", err)
               }
               version = v
           }
           if version == 1 {
               return manifestFileV1Reader, nil
           }
           return manifestFileReader, nil
       }))
       if err != nil {
           return nil, err
       }
   
       switch version {
       case 1:
           return decodeManifestsWithFallback[*manifestFileV1](rd)
       default:
           return decodeManifests[*manifestFile](rd, version)
       }
   }
   ```


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