rambleraptor commented on code in PR #85:
URL:
https://github.com/apache/terraform-provider-iceberg/pull/85#discussion_r3707689793
##########
internal/provider/table_schema.go:
##########
@@ -102,6 +102,142 @@ func (s *icebergTableSchema) FromIceberg(icebergSchema
*iceberg.Schema) error {
return json.Unmarshal(b, s)
}
+// fieldIDUnset reports an unspecified field ID: null, unknown, or 0 (Iceberg
+// reserves 0 for the table root).
+func fieldIDUnset(id types.Int64) bool {
+ return id.IsNull() || id.IsUnknown() || id.ValueInt64() == 0
+}
+
+// assignFieldIDs fills unset IDs (nested struct/list/map included) with fresh
+// values above startAfter and every existing ID, preserving user-set ones.
Pass
+// the table's last-column-id on update.
+func (s *icebergTableSchema) assignFieldIDs(startAfter int64) {
+ maxID := startAfter
+
+ var scan func(fields []icebergTableSchemaField)
+ scan = func(fields []icebergTableSchemaField) {
+ for _, f := range fields {
+ maxID = maxSetID(maxID, f.ID)
+ if f.ListProperties != nil {
+ maxID = maxSetID(maxID, f.ListProperties.ID)
+ }
+ if f.MapProperties != nil {
+ maxID = maxSetID(maxID, f.MapProperties.KeyID)
+ maxID = maxSetID(maxID, f.MapProperties.ValueID)
+ }
+ if f.StructProperties != nil {
+ scan(f.StructProperties.Fields)
+ }
+ }
+ }
+ scan(s.Fields)
+
+ next := func() types.Int64 {
+ maxID++
+
+ return types.Int64Value(maxID)
+ }
+
+ var assign func(fields []icebergTableSchemaField)
+ assign = func(fields []icebergTableSchemaField) {
+ for i := range fields {
+ f := &fields[i]
+ if fieldIDUnset(f.ID) {
+ f.ID = next()
+ }
+ if f.ListProperties != nil &&
fieldIDUnset(f.ListProperties.ID) {
+ f.ListProperties.ID = next()
+ }
+ if f.MapProperties != nil {
+ if fieldIDUnset(f.MapProperties.KeyID) {
+ f.MapProperties.KeyID = next()
+ }
+ if fieldIDUnset(f.MapProperties.ValueID) {
+ f.MapProperties.ValueID = next()
+ }
+ }
+ if f.StructProperties != nil {
+ assign(f.StructProperties.Fields)
+ }
+ }
+ }
+ assign(s.Fields)
+}
+
+func maxSetID(current int64, id types.Int64) int64 {
+ if fieldIDUnset(id) {
+ return current
+ }
+ if v := id.ValueInt64(); v > current {
+ return v
+ }
+
+ return current
+}
+
+// fieldIDs holds one field's IDs: the field plus any list/map
element/key/value.
+type fieldIDs struct {
+ id types.Int64
+ element types.Int64
+ key types.Int64
+ value types.Int64
+}
+
+// resolveFieldIDs reuses prior IDs for same-named fields (matched by path, so
+// nested fields stay scoped to their parent), keeping IDs stable across
+// inserts/reorders. Fills only unset IDs.
+func (s *icebergTableSchema) resolveFieldIDs(prior *icebergTableSchema) {
+ byPath := map[string]fieldIDs{}
+
+ var index func(path string, fields []icebergTableSchemaField)
+ index = func(path string, fields []icebergTableSchemaField) {
+ for _, f := range fields {
+ key := path + "/" + f.Name
Review Comment:
That's a great note on renames (and on validation for duplicate IDs).
I added a note to the docs about renaming columns.
--
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]