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 71bab97fd refactor(udf)!: remove NewSQLRepresentation in favor of 
struct literals (#2318)
71bab97fd is described below

commit 71bab97fd3638c7cae003d4daeaccab57b57eff1
Author: Minh Vu <[email protected]>
AuthorDate: Mon Oct 26 20:28:21 2026 +0100

    refactor(udf)!: remove NewSQLRepresentation in favor of struct literals 
(#2318)
    
    * refactor(udf)!: require named SQL representation fields
    
    Signed-off-by: Minh Vu <[email protected]>
    
    * chore: sync release notes with main to resolve conflicts
    
    * refactor(udf): remove redundant SQL representation constructor
    
    Use named struct literals, cover metadata validation on build, and
    restore the v0.7.0 compatibility note.
    
    Signed-off-by: Minh Vu <[email protected]>
    
    ---------
    
    Signed-off-by: Minh Vu <[email protected]>
    Co-authored-by: Matt Topol <[email protected]>
---
 udf/metadata.go              | 13 -------------
 udf/metadata_builder_test.go | 40 ++++++++++++++++++++++++++++++++++++----
 udf/metadata_test.go         | 15 ++++++---------
 website/src/releases.md      |  1 +
 4 files changed, 43 insertions(+), 26 deletions(-)

diff --git a/udf/metadata.go b/udf/metadata.go
index 69c914736..7b206731a 100644
--- a/udf/metadata.go
+++ b/udf/metadata.go
@@ -91,19 +91,6 @@ type SQLRepresentation struct {
        SQL     string `json:"sql"`
 }
 
-// NewSQLRepresentation creates a SQL representation from a dialect
-// identifier (e.g. "spark", "trino") and a SQL expression.
-func NewSQLRepresentation(dialect, sql string) (SQLRepresentation, error) {
-       if dialect == "" {
-               return SQLRepresentation{}, fmt.Errorf("%w: sql representation 
requires a dialect", ErrInvalidUDFMetadata)
-       }
-       if sql == "" {
-               return SQLRepresentation{}, fmt.Errorf("%w: sql representation 
requires a sql expression", ErrInvalidUDFMetadata)
-       }
-
-       return SQLRepresentation{Dialect: dialect, SQL: sql}, nil
-}
-
 func (SQLRepresentation) RepresentationType() string { return "sql" }
 func (SQLRepresentation) isRepresentation()          {}
 func (r SQLRepresentation) clone() Representation    { return r }
diff --git a/udf/metadata_builder_test.go b/udf/metadata_builder_test.go
index 8c94990fd..dd777e040 100644
--- a/udf/metadata_builder_test.go
+++ b/udf/metadata_builder_test.go
@@ -40,8 +40,7 @@ func newTestDefinition(t *testing.T) *Definition {
 
 func newTestVersion(t *testing.T, sql string, timestampMS int64) 
*DefinitionVersion {
        t.Helper()
-       repr, err := NewSQLRepresentation("trino", sql)
-       require.NoError(t, err)
+       repr := SQLRepresentation{Dialect: "trino", SQL: sql}
        version, err := NewDefinitionVersion([]Representation{repr},
                WithTimestampMS(timestampMS), WithDeterministic(true))
        require.NoError(t, err)
@@ -100,6 +99,40 @@ func TestBuildRejectsNilRepresentation(t *testing.T) {
        assert.ErrorContains(t, err, "representations must not contain null 
entries")
 }
 
+func TestBuildRejectsMissingSQLRepresentationFields(t *testing.T) {
+       tests := []struct {
+               name    string
+               repr    SQLRepresentation
+               wantErr string
+       }{
+               {
+                       name:    "missing dialect",
+                       repr:    SQLRepresentation{SQL: "x + 1"},
+                       wantErr: "without a dialect",
+               },
+               {
+                       name:    "missing SQL",
+                       repr:    SQLRepresentation{Dialect: "trino"},
+                       wantErr: "without a sql expression",
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       version, err := 
NewDefinitionVersion([]Representation{tt.repr}, WithTimestampMS(1000))
+                       require.NoError(t, err)
+
+                       builder := NewMetadataBuilder()
+                       _, err = builder.
+                               AddDefinition(newTestDefinition(t)).
+                               AddDefinitionVersion("int", version).
+                               Build()
+                       require.ErrorIs(t, err, ErrInvalidUDFMetadata)
+                       assert.ErrorContains(t, err, tt.wantErr)
+               })
+       }
+}
+
 func TestBuildNewMetadata(t *testing.T) {
        builder := NewMetadataBuilder()
 
@@ -462,8 +495,7 @@ func TestBuilderRejectsHandBuiltUnknownRepresentation(t 
*testing.T) {
 }
 
 func TestBuilderOnNullInput(t *testing.T) {
-       repr, err := NewSQLRepresentation("trino", "coalesce(x, 0)")
-       require.NoError(t, err)
+       repr := SQLRepresentation{Dialect: "trino", SQL: "coalesce(x, 0)"}
        version, err := NewDefinitionVersion([]Representation{repr},
                WithTimestampMS(1000), WithOnNullInput(OnNullInputReturnNull))
        require.NoError(t, err)
diff --git a/udf/metadata_test.go b/udf/metadata_test.go
index 9dea80072..068a4d7de 100644
--- a/udf/metadata_test.go
+++ b/udf/metadata_test.go
@@ -287,16 +287,13 @@ func TestMetadataInitDefaults(t *testing.T) {
        assert.False(t, ok)
 }
 
-func TestNewSQLRepresentation(t *testing.T) {
-       repr, err := NewSQLRepresentation("trino", "x + 1")
-       require.NoError(t, err)
-       assert.Equal(t, SQLRepresentation{Dialect: "trino", SQL: "x + 1"}, repr)
-
-       _, err = NewSQLRepresentation("", "x + 1")
-       assert.ErrorIs(t, err, ErrInvalidUDFMetadata)
+func TestSQLRepresentation(t *testing.T) {
+       repr := SQLRepresentation{Dialect: "trino", SQL: "x + 1"}
+       assert.Equal(t, "sql", repr.RepresentationType())
 
-       _, err = NewSQLRepresentation("trino", "")
-       assert.ErrorIs(t, err, ErrInvalidUDFMetadata)
+       data, err := json.Marshal(repr)
+       require.NoError(t, err)
+       assert.JSONEq(t, `{"type":"sql","dialect":"trino","sql":"x + 1"}`, 
string(data))
 }
 
 // minimalMetadata returns a decoded minimal valid metadata document for
diff --git a/website/src/releases.md b/website/src/releases.md
index 723138fd8..409c8646f 100644
--- a/website/src/releases.md
+++ b/website/src/releases.md
@@ -42,6 +42,7 @@ Per-release notes (highlights, breaking changes, 
contributors) are published on
 
 ### Unreleased compatibility notes
 
+- **SQL UDF representations now use struct literals.** The 
`udf.NewSQLRepresentation(dialect, sql)` function, available since v0.7.0, is 
removed. Use `udf.SQLRepresentation{Dialect: "trino", SQL: "x + 1"}` instead. 
Empty fields and duplicate dialects are checked during metadata validation; 
serialized JSON is unchanged.
 - **Filesystem adapter construction consolidated.** Replace 
`io.FSPreProcName(fsys, fn)` with `io.FS(fsys, io.WithNamePreprocessor(fn))`. 
Plain `io.FS(fsys)` remains supported.
 - **Table purge is required on catalogs.** The `catalog.Catalog` interface now 
embeds `catalog.PurgeableCatalog`; every custom catalog implementation must 
provide `PurgeTable(ctx, identifier) error`. The narrow 
`catalog.PurgeableTable` interface is renamed to `catalog.PurgeableCatalog`. 
Built-in purge behavior is unchanged.
 - **Unify statistics blob types with Puffin.** Replace `table.BlobType` with 
`puffin.BlobType` when constructing `table.BlobMetadata`. Replace 
`table.BlobTypeApacheDatasketchesThetaV1` with 
`puffin.BlobTypeDataSketchesTheta` and `table.BlobTypeDeletionVectorV1` with 
`puffin.BlobTypeDeletionVector`. Use `puffin.BlobType.IsKnown()` to identify 
the types defined by the Puffin specification; the redundant 
`table.BlobType.IsValid()` method is removed. Unknown non-empty blob type names 
still r [...]

Reply via email to