You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by ze...@apache.org on 2026/08/07 15:52:40 UTC

(iceberg-go) branch main updated: fix(rest): accept legacy content enum values (#1660)

This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 805bca98 fix(rest): accept legacy content enum values (#1660)
805bca98 is described below

commit 805bca98c2ae695c3ff6d4f0ad5a11f0cfb296b0
Author: Minh Vu <vu...@gmail.com>
AuthorDate: Fri Aug 7 17:52:34 2026 +0200

    fix(rest): accept legacy content enum values (#1660)
---
 catalog/rest/scan_task_decoder.go      | 25 +++++++++++++++++--------
 catalog/rest/scan_task_decoder_test.go | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/catalog/rest/scan_task_decoder.go b/catalog/rest/scan_task_decoder.go
index 680351b6..2549f220 100644
--- a/catalog/rest/scan_task_decoder.go
+++ b/catalog/rest/scan_task_decoder.go
@@ -305,13 +305,8 @@ func decodeRESTDeleteFile(
 	metadata table.ScanPlanningMetadata,
 	referencedDataFile string,
 ) (iceberg.DataFile, error) {
-	var content iceberg.ManifestEntryContent
-	switch wire.Content {
-	case "position-deletes":
-		content = iceberg.EntryContentPosDeletes
-	case "equality-deletes":
-		content = iceberg.EntryContentEqDeletes
-	default:
+	content, ok := parseRESTFileContent(wire.Content)
+	if !ok || content == iceberg.EntryContentData {
 		return nil, fmt.Errorf("unknown delete content %q", wire.Content)
 	}
 
@@ -387,12 +382,13 @@ func contentFileBuilder(
 	expectedContent iceberg.ManifestEntryContent,
 	metadata table.ScanPlanningMetadata,
 ) (*iceberg.DataFileBuilder, iceberg.FileFormat, error) {
+	actualContent, ok := parseRESTFileContent(wire.Content)
 	wantContent := map[iceberg.ManifestEntryContent]string{
 		iceberg.EntryContentData:       "data",
 		iceberg.EntryContentPosDeletes: "position-deletes",
 		iceberg.EntryContentEqDeletes:  "equality-deletes",
 	}[expectedContent]
-	if wire.Content != wantContent {
+	if !ok || actualContent != expectedContent {
 		return nil, "", fmt.Errorf("content is %q, want %q", wire.Content, wantContent)
 	}
 	if wire.RecordCount <= 0 {
@@ -458,6 +454,19 @@ func contentFileBuilder(
 	return builder, format, nil
 }
 
+func parseRESTFileContent(value string) (iceberg.ManifestEntryContent, bool) {
+	switch value {
+	case "data", "DATA":
+		return iceberg.EntryContentData, true
+	case "position-deletes", "POSITION_DELETES":
+		return iceberg.EntryContentPosDeletes, true
+	case "equality-deletes", "EQUALITY_DELETES":
+		return iceberg.EntryContentEqDeletes, true
+	default:
+		return 0, false
+	}
+}
+
 func decodePartition(
 	values []json.RawMessage,
 	spec *iceberg.PartitionSpec,
diff --git a/catalog/rest/scan_task_decoder_test.go b/catalog/rest/scan_task_decoder_test.go
index 0b0c82d1..0dcb8665 100644
--- a/catalog/rest/scan_task_decoder_test.go
+++ b/catalog/rest/scan_task_decoder_test.go
@@ -140,6 +140,31 @@ func TestDecodeScanTasksFullPayload(t *testing.T) {
 	assert.Equal(t, int64Ptr(50), dv.ContentSizeInBytes())
 }
 
+func TestDecodeScanTasksAcceptsLegacyJavaContentValues(t *testing.T) {
+	t.Parallel()
+
+	metadata := newScanTaskDecoderMetadata()
+	for _, tt := range []struct {
+		name       string
+		deleteType string
+		equalityID []int
+	}{
+		{name: "position deletes", deleteType: "POSITION_DELETES"},
+		{name: "equality deletes", deleteType: "EQUALITY_DELETES", equalityID: []int{1}},
+	} {
+		t.Run(tt.name, func(t *testing.T) {
+			wire := validScanTasksWire()
+			wire.FileScanTasks[0].DataFile.Content = "DATA"
+			wire.DeleteFiles[0].Content = tt.deleteType
+			wire.DeleteFiles[0].EqualityIDs = tt.equalityID
+
+			tasks, err := DecodeScanTasks(wire, metadata, metadata.schema, nil)
+			require.NoError(t, err)
+			require.Len(t, tasks, 1)
+		})
+	}
+}
+
 func TestDecodeScanTasksUsesFallbackAndAcceptsSpecConstants(t *testing.T) {
 	t.Parallel()
 
@@ -307,6 +332,13 @@ func TestDecodeScanTasksRejectsMalformedPayloads(t *testing.T) {
 			},
 			want: "unknown partition spec ID 99",
 		},
+		{
+			name: "unknown content",
+			mutate: func(w *ScanTasks) {
+				w.FileScanTasks[0].DataFile.Content = "Data"
+			},
+			want: `content is "Data", want "data"`,
+		},
 		{
 			name: "wrong partition width",
 			mutate: func(w *ScanTasks) {