fix(table): remove inconsistencies in metadata serialize (#350)
fixes #345
---------
Co-authored-by: Kevin Liu <kevinjqliu@users.noreply.github.com>
diff --git a/table/metadata.go b/table/metadata.go
index 08d5512..44986d5 100644
--- a/table/metadata.go
+++ b/table/metadata.go
@@ -828,14 +828,14 @@
Specs []iceberg.PartitionSpec `json:"partition-specs"`
DefaultSpecID int `json:"default-spec-id"`
LastPartitionID *int `json:"last-partition-id,omitempty"`
- Props iceberg.Properties `json:"properties"`
+ Props iceberg.Properties `json:"properties,omitempty"`
SnapshotList []Snapshot `json:"snapshots,omitempty"`
CurrentSnapshotID *int64 `json:"current-snapshot-id,omitempty"`
- SnapshotLog []SnapshotLogEntry `json:"snapshot-log"`
- MetadataLog []MetadataLogEntry `json:"metadata-log"`
+ SnapshotLog []SnapshotLogEntry `json:"snapshot-log,omitempty"`
+ MetadataLog []MetadataLogEntry `json:"metadata-log,omitempty"`
SortOrderList []SortOrder `json:"sort-orders"`
DefaultSortOrderID int `json:"default-sort-order-id"`
- SnapshotRefs map[string]SnapshotRef `json:"refs"`
+ SnapshotRefs map[string]SnapshotRef `json:"refs,omitempty"`
}
func (c *commonMetadata) Ref() SnapshotRef { return c.SnapshotRefs[MainBranch] }
@@ -1094,8 +1094,8 @@
func (c *commonMetadata) Version() int { return c.FormatVersion }
type metadataV1 struct {
- Schema *iceberg.Schema `json:"schema"`
- Partition []iceberg.PartitionField `json:"partition-spec"`
+ Schema *iceberg.Schema `json:"schema,omitempty"`
+ Partition []iceberg.PartitionField `json:"partition-spec,omitempty"`
commonMetadata
}
diff --git a/table/metadata_internal_test.go b/table/metadata_internal_test.go
index e28dfd4..9e33678 100644
--- a/table/metadata_internal_test.go
+++ b/table/metadata_internal_test.go
@@ -206,8 +206,54 @@
data, err := json.Marshal(&meta)
require.NoError(t, err)
- assert.JSONEq(t, `{"location": "s3://bucket/test/location", "table-uuid": "d20125c8-7284-442c-9aea-15fee620737c", "last-updated-ms": 1602638573874, "last-column-id": 3, "schemas": [{"type": "struct", "fields": [{"id": 1, "name": "x", "type": "long", "required": true}, {"id": 2, "name": "y", "type": "long", "required": true, "doc": "comment"}, {"id": 3, "name": "z", "type": "long", "required": true}], "schema-id": 0, "identifier-field-ids": []}], "current-schema-id": 0, "partition-specs": [{"spec-id": 0, "fields": [{"source-id": 1, "field-id": 1000, "transform": "identity", "name": "x"}]}], "default-spec-id": 0, "last-partition-id": 1000, "properties": {}, "snapshots": [{"snapshot-id": 1925, "sequence-number": 0, "timestamp-ms": 1602638573822}], "snapshot-log": [], "metadata-log": [], "sort-orders": [{"order-id": 0, "fields": []}], "default-sort-order-id": 0, "refs": {}, "format-version": 1, "schema": {"type": "struct", "fields": [{"id": 1, "name": "x", "type": "long", "required": true}, {"id": 2, "name": "y", "type": "long", "required": true, "doc": "comment"}, {"id": 3, "name": "z", "type": "long", "required": true}], "schema-id": 0, "identifier-field-ids": []}, "partition-spec": [{"name": "x", "transform": "identity", "source-id": 1, "field-id": 1000}]}`,
- string(data))
+ assert.JSONEq(t, `{
+ "location": "s3://bucket/test/location",
+ "table-uuid": "d20125c8-7284-442c-9aea-15fee620737c",
+ "last-updated-ms": 1602638573874,
+ "last-column-id": 3,
+ "schemas": [
+ {
+ "type": "struct",
+ "fields": [
+ {"id": 1, "name": "x", "type": "long", "required": true},
+ {"id": 2, "name": "y", "type": "long", "required": true, "doc": "comment"},
+ {"id": 3, "name": "z", "type": "long", "required": true}
+ ],
+ "schema-id": 0,
+ "identifier-field-ids": []
+ }
+ ],
+ "current-schema-id": 0,
+ "partition-specs": [
+ {
+ "spec-id": 0,
+ "fields": [
+ {"source-id": 1, "field-id": 1000, "transform": "identity", "name": "x"}
+ ]
+ }
+ ],
+ "default-spec-id": 0,
+ "last-partition-id": 1000,
+ "snapshots": [
+ {"snapshot-id": 1925, "sequence-number": 0, "timestamp-ms": 1602638573822}
+ ],
+ "sort-orders": [{"order-id": 0, "fields": []}],
+ "default-sort-order-id": 0,
+ "format-version": 1,
+ "schema": {
+ "type": "struct",
+ "fields": [
+ {"id": 1, "name": "x", "type": "long", "required": true},
+ {"id": 2, "name": "y", "type": "long", "required": true, "doc": "comment"},
+ {"id": 3, "name": "z", "type": "long", "required": true}
+ ],
+ "schema-id": 0,
+ "identifier-field-ids": []
+ },
+ "partition-spec": [
+ {"name": "x", "transform": "identity", "source-id": 1, "field-id": 1000}
+ ]
+ }`, string(data))
}
func TestSerializeMetadataV2(t *testing.T) {
@@ -615,3 +661,91 @@
assert.Truef(t, expected.Equals(actual), "expected: %s\ngot: %s", expected, actual)
}
+
+func TestMetadataV1Serialize(t *testing.T) {
+ sc := iceberg.NewSchema(0,
+ iceberg.NestedField{ID: 1, Name: "int", Type: iceberg.PrimitiveTypes.Int32})
+ toserialize := &metadataV1{
+ commonMetadata: commonMetadata{
+ FormatVersion: 1,
+ UUID: uuid.MustParse("dd93fa46-a1a7-43bb-8748-6cc7eff107a3"),
+ Loc: "s3a://warehouse/iceberg/iceberg-test-2.db/test-table-2",
+ LastUpdatedMS: 1742412491193,
+ LastColumnId: 1,
+ SchemaList: []*iceberg.Schema{sc},
+ CurrentSchemaID: 0,
+ Specs: []iceberg.PartitionSpec{*iceberg.UnpartitionedSpec},
+ DefaultSpecID: 0,
+ SortOrderList: []SortOrder{UnsortedSortOrder},
+ DefaultSortOrderID: 0,
+ },
+ }
+
+ data, err := json.Marshal(toserialize)
+ require.NoError(t, err)
+ assert.JSONEq(t, `{
+ "format-version":1,
+ "table-uuid":"dd93fa46-a1a7-43bb-8748-6cc7eff107a3",
+ "location":"s3a://warehouse/iceberg/iceberg-test-2.db/test-table-2",
+ "last-updated-ms":1742412491193,
+ "last-column-id":1,
+ "schemas": [
+ {
+ "type":"struct",
+ "fields":[{"type":"int","id":1,"name":"int","required":false}],
+ "schema-id":0,
+ "identifier-field-ids":[]
+ }
+ ],
+ "current-schema-id":0,
+ "partition-specs":[{"spec-id":0,"fields":[]}],
+ "default-spec-id":0,
+ "sort-orders":[{"order-id":0,"fields":[]}],
+ "default-sort-order-id":0
+ }`, string(data))
+}
+
+func TestMetadataV2Serialize(t *testing.T) {
+ sc := iceberg.NewSchema(0,
+ iceberg.NestedField{ID: 1, Name: "int", Type: iceberg.PrimitiveTypes.Int32})
+ toserialize := &metadataV2{
+ LastSeqNum: 1,
+ commonMetadata: commonMetadata{
+ FormatVersion: 1,
+ UUID: uuid.MustParse("dd93fa46-a1a7-43bb-8748-6cc7eff107a3"),
+ Loc: "s3a://warehouse/iceberg/iceberg-test-2.db/test-table-2",
+ LastUpdatedMS: 1742412491193,
+ LastColumnId: 1,
+ SchemaList: []*iceberg.Schema{sc},
+ CurrentSchemaID: 0,
+ Specs: []iceberg.PartitionSpec{*iceberg.UnpartitionedSpec},
+ DefaultSpecID: 0,
+ SortOrderList: []SortOrder{UnsortedSortOrder},
+ DefaultSortOrderID: 0,
+ },
+ }
+
+ data, err := json.Marshal(toserialize)
+ require.NoError(t, err)
+ assert.JSONEq(t, `{
+ "last-sequence-number": 1,
+ "format-version":1,
+ "table-uuid":"dd93fa46-a1a7-43bb-8748-6cc7eff107a3",
+ "location":"s3a://warehouse/iceberg/iceberg-test-2.db/test-table-2",
+ "last-updated-ms":1742412491193,
+ "last-column-id":1,
+ "schemas": [
+ {
+ "type":"struct",
+ "fields":[{"type":"int","id":1,"name":"int","required":false}],
+ "schema-id":0,
+ "identifier-field-ids":[]
+ }
+ ],
+ "current-schema-id":0,
+ "partition-specs":[{"spec-id":0,"fields":[]}],
+ "default-spec-id":0,
+ "sort-orders":[{"order-id":0,"fields":[]}],
+ "default-sort-order-id":0
+ }`, string(data))
+}