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 [...]