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/10/23 16:37:01 UTC

(iceberg-go) branch main updated: fix(view): copy inputs when creating v1 versions (#2274)

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 7e71d9423 fix(view): copy inputs when creating v1 versions (#2274)
7e71d9423 is described below

commit 7e71d94239c79913c856c3830b8bcaf14851c029
Author: Minh Vu <vu...@gmail.com>
AuthorDate: Fri Oct 23 18:36:55 2026 +0200

    fix(view): copy inputs when creating v1 versions (#2274)
    
    * fix(view): copy v1 view version constructor inputs
    
    Copy the supplied representations and default namespace so caller mutations
    cannot change an already validated view version.
    
    Signed-off-by: Minh Vu <vu...@gmail.com>
    
    * test(view): match representation slice type in copy assertion
    
    ---------
    
    Signed-off-by: Minh Vu <vu...@gmail.com>
---
 view/metadata.go              |  6 ++++--
 view/metadata_builder_test.go | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/view/metadata.go b/view/metadata.go
index 872694271..2c0af1c1a 100644
--- a/view/metadata.go
+++ b/view/metadata.go
@@ -159,6 +159,8 @@ func WithTimestampMS(timestampMS int64) VersionOpt {
 }
 
 // NewVersion creates a Version instance from the provided parameters.
+// It copies the representations and namespace so later changes to the inputs
+// cannot modify the returned version.
 // If building updates using the MetadataBuilder, and one desires to use the last
 // added schema ID, one should use the LastAddedID constant as the provided schemaID
 //
@@ -188,10 +190,10 @@ func NewVersion(id int64, schemaID int, representations []Representation, defaul
 	version := &Version{
 		VersionID:        id,
 		SchemaID:         schemaID,
-		Representations:  representations,
+		Representations:  slices.Clone(representations),
 		Summary:          VersionSummary{viewEngineProperty: defaultViewEngine},
 		TimestampMS:      time.Now().UnixMilli(),
-		DefaultNamespace: defaultNS,
+		DefaultNamespace: slices.Clone(defaultNS),
 	}
 
 	for _, opt := range opts {
diff --git a/view/metadata_builder_test.go b/view/metadata_builder_test.go
index 753bed0df..b9c1d9066 100644
--- a/view/metadata_builder_test.go
+++ b/view/metadata_builder_test.go
@@ -246,6 +246,45 @@ func TestNewVersion_RepresentationValidation(t *testing.T) {
 	}
 }
 
+func TestNewVersionCopiesInputSlices(t *testing.T) {
+	representations := Representations{
+		NewRepresentation("SELECT 1", "spark"),
+		NewRepresentation("SELECT 2", "trino"),
+	}
+	defaultNS := table.Identifier{"analytics", "reporting"}
+
+	version, err := NewVersion(1, 0, representations, defaultNS)
+	require.NoError(t, err)
+
+	// These mutations would otherwise change an already validated version,
+	// including making the representation dialects duplicate.
+	representations[0].Sql = "SELECT changed"
+	representations[1].Dialect = "spark"
+	defaultNS[0] = "other"
+	defaultNS[1] = "schema"
+
+	assert.Equal(t, []Representation{
+		NewRepresentation("SELECT 1", "spark"),
+		NewRepresentation("SELECT 2", "trino"),
+	}, version.Representations)
+	assert.Equal(t, table.Identifier{"analytics", "reporting"}, version.DefaultNamespace)
+
+	// Neither side should share the backing storage with the other.
+	version.Representations[0].Sql = "SELECT from version"
+	version.DefaultNamespace[0] = "version"
+	assert.Equal(t, "SELECT changed", representations[0].Sql)
+	assert.Equal(t, "other", defaultNS[0])
+}
+
+func TestNewVersionFromSQLCopiesNamespace(t *testing.T) {
+	defaultNS := table.Identifier{"analytics"}
+	version, err := NewVersionFromSQL(1, 0, "SELECT 1", defaultNS)
+	require.NoError(t, err)
+
+	defaultNS[0] = "other"
+	assert.Equal(t, table.Identifier{"analytics"}, version.DefaultNamespace)
+}
+
 func TestAddVersion_InvalidRepresentation_Validation(t *testing.T) {
 	invalidVersion := &Version{
 		VersionID: 1,