zeroshade commented on code in PR #1514:
URL: https://github.com/apache/iceberg-go/pull/1514#discussion_r3647331336


##########
partitions.go:
##########
@@ -422,15 +422,47 @@ func (ps PartitionSpec) MarshalJSON() ([]byte, error) {
 
 func (ps *PartitionSpec) UnmarshalJSON(b []byte) error {
        aux := struct {
-               ID     int              `json:"spec-id"`
-               Fields []PartitionField `json:"fields"`
-       }{ID: ps.id, Fields: ps.fields}
+               ID     int               `json:"spec-id"`
+               Fields []json.RawMessage `json:"fields"`
+       }{ID: ps.id}
 
        if err := json.Unmarshal(b, &aux); err != nil {
                return err
        }
 
-       ps.id, ps.fields = aux.ID, aux.Fields
+       fields := make([]PartitionField, len(aux.Fields))
+       fieldIDCount := 0
+       for i, rawField := range aux.Fields {
+               var keys map[string]json.RawMessage
+               if err := json.Unmarshal(rawField, &keys); err != nil {
+                       return err
+               }
+               if rawFieldID, ok := keys["field-id"]; ok {
+                       var fieldID *int
+                       if err := json.Unmarshal(rawFieldID, &fieldID); err != 
nil {
+                               return fmt.Errorf("%w: invalid partition field 
ID: %w", ErrInvalidPartitionSpec, err)
+                       }
+                       if fieldID == nil {
+                               return fmt.Errorf("%w: partition field ID 
cannot be null", ErrInvalidPartitionSpec)
+                       }
+                       fieldIDCount++
+               }
+               if err := json.Unmarshal(rawField, &fields[i]); err != nil {
+                       return err
+               }
+       }
+
+       if fieldIDCount != 0 && fieldIDCount != len(fields) {
+               return fmt.Errorf("%w: cannot parse spec with missing field 
IDs: %d missing of %d fields",
+                       ErrInvalidPartitionSpec, len(fields)-fieldIDCount, 
len(fields))
+       }
+       if fieldIDCount == 0 {

Review Comment:
   All-missing assigns `PartitionDataIDStart + i` per spec. With no table-level 
`last-partition-id`/existing-id context, multiple specs parsed from the same 
metadata each assign 1000, 1001, … and collide across the table-wide 
partition-field-id space (also watch for collision with an existing field 
already using 1000/1001).



##########
partitions.go:
##########
@@ -422,15 +422,47 @@ func (ps PartitionSpec) MarshalJSON() ([]byte, error) {
 
 func (ps *PartitionSpec) UnmarshalJSON(b []byte) error {
        aux := struct {
-               ID     int              `json:"spec-id"`
-               Fields []PartitionField `json:"fields"`
-       }{ID: ps.id, Fields: ps.fields}
+               ID     int               `json:"spec-id"`
+               Fields []json.RawMessage `json:"fields"`
+       }{ID: ps.id}
 
        if err := json.Unmarshal(b, &aux); err != nil {
                return err
        }
 
-       ps.id, ps.fields = aux.ID, aux.Fields
+       fields := make([]PartitionField, len(aux.Fields))
+       fieldIDCount := 0
+       for i, rawField := range aux.Fields {
+               var keys map[string]json.RawMessage
+               if err := json.Unmarshal(rawField, &keys); err != nil {
+                       return err
+               }
+               if rawFieldID, ok := keys["field-id"]; ok {
+                       var fieldID *int
+                       if err := json.Unmarshal(rawFieldID, &fieldID); err != 
nil {
+                               return fmt.Errorf("%w: invalid partition field 
ID: %w", ErrInvalidPartitionSpec, err)
+                       }
+                       if fieldID == nil {
+                               return fmt.Errorf("%w: partition field ID 
cannot be null", ErrInvalidPartitionSpec)
+                       }
+                       fieldIDCount++
+               }
+               if err := json.Unmarshal(rawField, &fields[i]); err != nil {
+                       return err
+               }
+       }
+
+       if fieldIDCount != 0 && fieldIDCount != len(fields) {

Review Comment:
   Mixed set/unset partition field ids are rejected here. Expected behavior is 
to preserve existing ids and assign fresh ids only to the missing fields.



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