This is an automated email from the ASF dual-hosted git repository.
laskoviymishka 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 96acf3731 build: bump minimum Go version to 1.26 (#2077)
96acf3731 is described below
commit 96acf3731636165ad0f4ae431bb9589e3a360cf2
Author: Matt Topol <[email protected]>
AuthorDate: Wed Sep 30 15:12:42 2026 -0400
build: bump minimum Go version to 1.26 (#2077)
* fix(puffin): report LZ4 read errors when footer decoder stops early
Since Go 1.27, encoding/json's Decoder.More returns true on non-EOF read
errors, so a corrupted compressed footer surfaced as "unexpected content
after footer JSON" instead of the underlying LZ4 checksum error.
* build: bump minimum Go version to 1.26
- go.mod: go 1.26.0
- CI: test matrix 1.26.8 / 1.27.1; cross-compile and Arrow assertions on
1.27.1; integration on 1.26
- golangci-lint v2.14.0 (v2.12.2 is built with go1.26 and panics on the
Go 1.27 stdlib)
- apply modernize fixes enabled by go 1.26 (errors.AsType, new(expr),
reflect iterators) and drop the now-redundant pointer helpers
- docs: Go 1.26 or later
---
.github/workflows/go-ci.yml | 8 +-
.github/workflows/go-integration.yml | 2 +-
.pre-commit-config.yaml | 2 +-
Makefile | 2 +-
README.md | 4 +-
catalog/glue/glue.go | 6 +-
catalog/hive/hive.go | 3 +-
catalog/rest/auth.go | 3 +-
catalog/rest/scan_planning.go | 3 +-
catalog/rest/scan_planning_parity_test.go | 10 +-
catalog/rest/scan_planning_retry.go | 3 +-
catalog/rest/scan_planning_test.go | 11 +-
catalog/rest/scan_task_decoder_bench_test.go | 6 +-
catalog/rest/scan_task_decoder_test.go | 32 ++--
catalog/rest/wait_for_plan_test.go | 2 +-
catalog/sql/sql.go | 3 +-
cmd/iceberg/upgrade_rollback_test.go | 16 +-
codec/data_file_test.go | 4 +-
go.mod | 2 +-
literals.go | 9 +-
manifest.go | 2 +-
manifest_test.go | 4 +-
name_mapping_test.go | 210 ++++++++++-----------
partitions.go | 3 +-
puffin/puffin_reader.go | 15 +-
table/arrow_utils.go | 3 +-
table/arrow_utils_test.go | 46 +++--
table/dv/deletion_vector_bench_test.go | 2 +-
table/dv/deletion_vector_test.go | 18 +-
table/dv_scan_planning_test.go | 75 ++++----
table/dv_scanner_read_test.go | 14 +-
table/incremental_append_scan_test.go | 12 +-
table/incremental_changelog_scan_test.go | 20 +-
table/inspect_internal_test.go | 38 ++--
table/metadata_builder_internal_test.go | 8 +-
table/pos_delete_partitioned_fanout_writer_test.go | 4 -
table/rebuild_manifest_test.go | 6 +-
table/requirement_test.go | 12 +-
table/scan_metrics_test.go | 10 +-
table/scan_planning.go | 2 +-
table/scanner_empty_manifest_bench_test.go | 2 +-
table/scanner_manifest_entries_bench_test.go | 6 +-
table/snapshot_producers.go | 24 +--
table/snapshot_producers_test.go | 6 +-
table/snapshots_test.go | 22 +--
table/sorting.go | 3 +-
table/substrait/substrait.go | 3 +-
table/transaction_internal_test.go | 30 ++-
website/src/install.md | 2 +-
49 files changed, 353 insertions(+), 380 deletions(-)
diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml
index aceeb3f5f..b17433228 100644
--- a/.github/workflows/go-ci.yml
+++ b/.github/workflows/go-ci.yml
@@ -46,7 +46,7 @@ jobs:
max-parallel: 15
fail-fast: false
matrix:
- go: [ '1.25.9', '1.26.1' ]
+ go: [ '1.26.8', '1.27.1' ]
os:
- 'ubuntu-latest'
- 'macos-latest'
@@ -83,7 +83,7 @@ jobs:
- name: Run golangci-lint
uses:
golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
with:
- version: v2.12.2
+ version: v2.14.0
args: --timeout=10m
# The action's own cache key omits the Go version, so all matrix cells
# collide on one entry; we manage the cache explicitly above instead.
@@ -91,7 +91,7 @@ jobs:
- name: Run tests with race detector
run: make test-race
- name: Run Arrow ownership assertions
- if: matrix.os == 'ubuntu-latest' && matrix.go == '1.26.1'
+ if: matrix.os == 'ubuntu-latest' && matrix.go == '1.27.1'
run: make test-assert
- name: Save Go module and build cache
if: github.ref == 'refs/heads/main'
@@ -126,7 +126,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
- go-version: '1.26.1'
+ go-version: '1.27.1'
cache: false
- name: Restore Go module and build cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #
v6.1.0
diff --git a/.github/workflows/go-integration.yml
b/.github/workflows/go-integration.yml
index 5e77bd377..bf5e15926 100644
--- a/.github/workflows/go-integration.yml
+++ b/.github/workflows/go-integration.yml
@@ -51,7 +51,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e #
v7.0.0
with:
- go-version: 1.25
+ go-version: '1.26'
# Caching managed explicitly below so saves can be gated to main.
cache: false
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 40eaa759f..61b51a7d4 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -17,7 +17,7 @@
---
repos:
- repo: https://github.com/golangci/golangci-lint
- rev: v2.12.2
+ rev: v2.14.0
hooks:
- id: golangci-lint
entry: bash -c 'golangci-lint run --fix --timeout 5m'
diff --git a/Makefile b/Makefile
index 741393ac7..2e49d69be 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@
# limitations under the License.
# golangci-lint version (keep in sync with CI and README)
-GOLANGCI_LINT_VERSION := v2.12.2
+GOLANGCI_LINT_VERSION := v2.14.0
.PHONY: test test-assert test-race lint lint-install integration-setup
integration-setup-spark4 integration-test integration-scanner integration-io
integration-rest integration-rest-scan-planning integration-spark
integration-hadoop integration-down integration-logs docs-gen
diff --git a/README.md b/README.md
index 23414a28b..01ec83776 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
### Prerequisites
-* Go 1.25 or later
+* Go 1.26 or later
### Build
@@ -54,7 +54,7 @@ Install the linter first
```shell
make lint-install
-# or: go install github.com/golangci/golangci-lint/v2/cmd/[email protected]
+# or: go install github.com/golangci/golangci-lint/v2/cmd/[email protected]
```
### Integration tests
diff --git a/catalog/glue/glue.go b/catalog/glue/glue.go
index d33abd274..db4fe7481 100644
--- a/catalog/glue/glue.go
+++ b/catalog/glue/glue.go
@@ -848,8 +848,7 @@ func (c *Catalog) getRawTable(ctx context.Context,
database, tableName string) (
},
)
if err != nil {
- var notFoundErr *types.EntityNotFoundException
- if errors.As(err, ¬FoundErr) {
+ if _, ok := errors.AsType[*types.EntityNotFoundException](err);
ok {
return nil, fmt.Errorf("failed to get table %s.%s: %w",
database, tableName, catalog.ErrNoSuchTable)
}
@@ -924,8 +923,7 @@ func (c *Catalog) convertGlueToIceberg(ctx context.Context,
glueTable *types.Tab
func (c *Catalog) getDatabase(ctx context.Context, databaseName string)
(*types.Database, error) {
database, err := c.glueSvc.GetDatabase(ctx,
&glue.GetDatabaseInput{CatalogId: c.catalogId, Name: aws.String(databaseName)})
if err != nil {
- var notFoundErr *types.EntityNotFoundException
- if errors.As(err, ¬FoundErr) {
+ if _, ok := errors.AsType[*types.EntityNotFoundException](err);
ok {
return nil, fmt.Errorf("failed to get namespace %s:
%w", databaseName, catalog.ErrNoSuchNamespace)
}
diff --git a/catalog/hive/hive.go b/catalog/hive/hive.go
index af4e206fb..8bcf9e77f 100644
--- a/catalog/hive/hive.go
+++ b/catalog/hive/hive.go
@@ -1032,8 +1032,7 @@ func isNoSuchObjectError(err error) bool {
return false
}
- var noSuchObjectErr *hive_metastore.NoSuchObjectException
- if errors.As(err, &noSuchObjectErr) {
+ if _, ok := errors.AsType[*hive_metastore.NoSuchObjectException](err);
ok {
return true
}
diff --git a/catalog/rest/auth.go b/catalog/rest/auth.go
index 97a8c7ca8..79db6534e 100644
--- a/catalog/rest/auth.go
+++ b/catalog/rest/auth.go
@@ -76,8 +76,7 @@ func (o *Oauth2AuthManager) AuthHeaderWithContext(ctx
context.Context) (string,
func (o *Oauth2AuthManager) authHeader() (string, string, error) {
tok, err := o.tokenSource.Token()
if err != nil {
- var re *oauth2.RetrieveError
- if errors.As(err, &re) {
+ if re, ok := errors.AsType[*oauth2.RetrieveError](err); ok {
return "", "", oauthError{
code: re.ErrorCode,
desc: re.ErrorDescription,
diff --git a/catalog/rest/scan_planning.go b/catalog/rest/scan_planning.go
index b8c974651..3ae6b6d70 100644
--- a/catalog/rest/scan_planning.go
+++ b/catalog/rest/scan_planning.go
@@ -893,8 +893,7 @@ func (r *Catalog) WaitForPlan(ctx context.Context, ident
table.Identifier, planI
// ErrServiceUnavailable preserves compatibility with callers or transports
that
// return the sentinel without the package's concrete errorResponse wrapper.
func scanPlanPollRetry(err error) (time.Duration, bool) {
- var restErr errorResponse
- if errors.As(err, &restErr) {
+ if restErr, ok := errors.AsType[errorResponse](err); ok {
switch restErr.statusCode {
case http.StatusRequestTimeout,
http.StatusTooManyRequests,
diff --git a/catalog/rest/scan_planning_parity_test.go
b/catalog/rest/scan_planning_parity_test.go
index 526f9ff52..98f60d13b 100644
--- a/catalog/rest/scan_planning_parity_test.go
+++ b/catalog/rest/scan_planning_parity_test.go
@@ -182,7 +182,7 @@ func newPlanningParityTable(t *testing.T) (table.Metadata,
*iceio.MemFS) {
b.SplitOffsets([]int64{4, 40, 70})
b.LowerBoundValues(map[int][]byte{2:
lo}).UpperBoundValues(map[int][]byte{2: hi})
b.ValueCounts(map[int]int64{1: 10, 2:
10}).NullValueCounts(map[int]int64{1: 0, 2: 0})
- entries = append(entries,
iceberg.NewManifestEntryBuilder(iceberg.EntryStatusADDED, parityPtr(int64(10)),
b.Build()).SequenceNum(1).Build())
+ entries = append(entries,
iceberg.NewManifestEntryBuilder(iceberg.EntryStatusADDED, new(int64(10)),
b.Build()).SequenceNum(1).Build())
}
var data bytes.Buffer
mf, err := iceberg.WriteManifest("mem://parity/data.avro", &data, 2,
spec, schema, 10, entries)
@@ -202,7 +202,7 @@ func newPlanningParityTable(t *testing.T) (table.Metadata,
*iceio.MemFS) {
if content == iceberg.EntryContentEqDeletes {
b.EqualityFieldIDs([]int{2})
}
- require.NoError(t,
writer.Add(iceberg.NewManifestEntryBuilder(iceberg.EntryStatusADDED,
parityPtr(int64(20)), b.Build()).SequenceNum(2).Build()))
+ require.NoError(t,
writer.Add(iceberg.NewManifestEntryBuilder(iceberg.EntryStatusADDED,
new(int64(20)), b.Build()).SequenceNum(2).Build()))
}
}
require.NoError(t, writer.Close())
@@ -221,7 +221,7 @@ func newPlanningParityTable(t *testing.T) (table.Metadata,
*iceio.MemFS) {
path := fmt.Sprintf("mem://parity/list-%d.avro", snapshotID)
var parentSnapshotID *int64
if i == 1 {
- parentSnapshotID = parityPtr(int64(10))
+ parentSnapshotID = new(int64(10))
}
var list bytes.Buffer
require.NoError(t, iceberg.WriteManifestList(2, &list,
snapshotID, parentSnapshotID, &seq, 0, manifests))
@@ -233,7 +233,7 @@ func newPlanningParityTable(t *testing.T) (table.Metadata,
*iceio.MemFS) {
}
require.NoError(t, builder.AddSnapshot(&table.Snapshot{
SnapshotID: snapshotID, ParentSnapshotID:
parentSnapshotID, SequenceNumber: seq,
- TimestampMs: time.Now().UnixMilli() + int64(i+1),
ManifestList: path, SchemaID: parityPtr(0),
+ TimestampMs: time.Now().UnixMilli() + int64(i+1),
ManifestList: path, SchemaID: new(0),
}))
}
require.NoError(t, builder.SetSnapshotRef("main", 20, table.BranchRef))
@@ -527,8 +527,6 @@ func parityDeletes(files []iceberg.DataFile) []parityDelete
{
return out
}
-func parityPtr[T any](v T) *T { return &v }
-
// Local residuals are already bound; wire residuals and the original filter
// are unbound. Preserve the former and bind the latter without a JSON round
// trip, so the comparison does not normalize through the codec under test.
diff --git a/catalog/rest/scan_planning_retry.go
b/catalog/rest/scan_planning_retry.go
index 79ace6471..c3fc47f49 100644
--- a/catalog/rest/scan_planning_retry.go
+++ b/catalog/rest/scan_planning_retry.go
@@ -44,8 +44,7 @@ func retryScanPlanning[T any](ctx context.Context, operation
string, request fun
return zero, err
}
result, err := request()
- var responseError errorResponse
- if !errors.As(err, &responseError) {
+ if _, ok := errors.AsType[errorResponse](err); !ok {
return result, err
}
retryAfter, retryable := scanPlanPollRetry(err)
diff --git a/catalog/rest/scan_planning_test.go
b/catalog/rest/scan_planning_test.go
index 093eca2cd..bf049a8ff 100644
--- a/catalog/rest/scan_planning_test.go
+++ b/catalog/rest/scan_planning_test.go
@@ -448,13 +448,13 @@ func TestPlanTableScanRequest(t *testing.T) {
name: "completed",
response:
`{"status":"completed","plan-id":"plan-1","plan-tasks":["task-1"]}`,
wantStatus: PlanStatusCompleted,
- wantPlanID: stringPtr("plan-1"),
+ wantPlanID: new("plan-1"),
},
{
name: "submitted",
response: `{"status":"submitted","plan-id":"plan-2"}`,
wantStatus: PlanStatusSubmitted,
- wantPlanID: stringPtr("plan-2"),
+ wantPlanID: new("plan-2"),
},
{
name: "failed",
@@ -957,8 +957,6 @@ func writeRESTNotFound(t *testing.T, w http.ResponseWriter,
errType string) {
require.NoError(t, err)
}
-func stringPtr(s string) *string { return &s }
-
// TestPlanTableScanRequestFromEncodesFilter checks the row filter serializes
to
// ExpressionParser JSON on the wire request, and that trivial filters are
// dropped so the server plans without one.
@@ -1059,8 +1057,9 @@ func scanFilterSchema() *iceberg.Schema {
// encoding needs.
type scanTestMetadata struct{ schema *iceberg.Schema }
-func (m scanTestMetadata) CurrentSchema() *iceberg.Schema {
return m.schema }
-func (m scanTestMetadata) Schemas() []*iceberg.Schema {
return []*iceberg.Schema{m.schema} }
+func (m scanTestMetadata) CurrentSchema() *iceberg.Schema { return m.schema }
+func (m scanTestMetadata) Schemas() []*iceberg.Schema { return
[]*iceberg.Schema{m.schema} }
+
func (m scanTestMetadata) PartitionSpec() iceberg.PartitionSpec {
return iceberg.PartitionSpec{} }
func (m scanTestMetadata) PartitionSpecByID(int) *iceberg.PartitionSpec {
return nil }
func (m scanTestMetadata) CurrentSnapshot() *table.Snapshot {
return nil }
diff --git a/catalog/rest/scan_task_decoder_bench_test.go
b/catalog/rest/scan_task_decoder_bench_test.go
index b22d56951..c7130484d 100644
--- a/catalog/rest/scan_task_decoder_bench_test.go
+++ b/catalog/rest/scan_task_decoder_bench_test.go
@@ -59,8 +59,8 @@ func deletionVectorScanTasksWire(taskCount int, explicitOwner
bool) ScanTasks {
dataFile := *base.FileScanTasks[0].DataFile
deleteFile := base.DeleteFiles[0]
deleteFile.FileFormat = "puffin"
- deleteFile.ContentOffset = int64Ptr(10)
- deleteFile.ContentSizeInBytes = int64Ptr(20)
+ deleteFile.ContentOffset = new(int64(10))
+ deleteFile.ContentSizeInBytes = new(int64(20))
wire := ScanTasks{
FileScanTasks: make([]RESTFileScanTask, taskCount),
@@ -72,7 +72,7 @@ func deletionVectorScanTasksWire(taskCount int, explicitOwner
bool) ScanTasks {
delete := deleteFile
delete.FilePath =
fmt.Sprintf("s3://bucket/table/delete-%d.puffin", i)
if explicitOwner {
- delete.ReferencedDataFile = stringPtr(data.FilePath)
+ delete.ReferencedDataFile = new(data.FilePath)
}
wire.FileScanTasks[i] = RESTFileScanTask{
diff --git a/catalog/rest/scan_task_decoder_test.go
b/catalog/rest/scan_task_decoder_test.go
index 9cd8de8a9..b796c4a17 100644
--- a/catalog/rest/scan_task_decoder_test.go
+++ b/catalog/rest/scan_task_decoder_test.go
@@ -114,8 +114,8 @@ func TestDecodeScanTasksFullPayload(t *testing.T) {
}, task.File.Partition())
assert.Equal(t, []byte{0x0a, 0x0b}, task.File.KeyMetadata())
assert.Equal(t, []int64{4, 128}, task.File.SplitOffsets())
- assert.Equal(t, intPtr(3), task.File.SortOrderID())
- assert.Equal(t, int64Ptr(99), task.FirstRowID)
+ assert.Equal(t, new(3), task.File.SortOrderID())
+ assert.Equal(t, new(int64(99)), task.FirstRowID)
assert.Equal(t, map[int]int64{1: 800, 2: 1200}, task.File.ColumnSizes())
assert.Equal(t, map[int]int64{1: 100, 2: 100}, task.File.ValueCounts())
assert.Equal(t, map[int]int64{1: 0, 2: 1}, task.File.NullValueCounts())
@@ -137,9 +137,9 @@ func TestDecodeScanTasksFullPayload(t *testing.T) {
require.Len(t, task.DeletionVectorFiles, 1)
dv := task.DeletionVectorFiles[0]
assert.Equal(t, iceberg.PuffinFile, dv.FileFormat())
- assert.Equal(t, stringPtr("s3://bucket/table/data.parquet"),
dv.ReferencedDataFile())
- assert.Equal(t, int64Ptr(25), dv.ContentOffset())
- assert.Equal(t, int64Ptr(50), dv.ContentSizeInBytes())
+ assert.Equal(t, new("s3://bucket/table/data.parquet"),
dv.ReferencedDataFile())
+ assert.Equal(t, new(int64(25)), dv.ContentOffset())
+ assert.Equal(t, new(int64(50)), dv.ContentSizeInBytes())
}
func TestDecodeScanTasksAcceptsLegacyJavaContentValues(t *testing.T) {
@@ -278,14 +278,14 @@ func
TestDecodeScanTasksDerivesDeletionVectorTargetWhenOmitted(t *testing.T) {
wire := validScanTasksWire()
wire.FileScanTasks[0].DeleteFileReferences = []int{0}
wire.DeleteFiles[0].FileFormat = "puffin"
- wire.DeleteFiles[0].ContentOffset = int64Ptr(10)
- wire.DeleteFiles[0].ContentSizeInBytes = int64Ptr(20)
+ wire.DeleteFiles[0].ContentOffset = new(int64(10))
+ wire.DeleteFiles[0].ContentSizeInBytes = new(int64(20))
tasks, err := DecodeScanTasks(wire, metadata, metadata.schema, nil)
require.NoError(t, err)
require.Len(t, tasks, 1)
require.Len(t, tasks[0].DeletionVectorFiles, 1)
- assert.Equal(t, stringPtr("s3://bucket/table/data.parquet"),
tasks[0].DeletionVectorFiles[0].ReferencedDataFile())
+ assert.Equal(t, new("s3://bucket/table/data.parquet"),
tasks[0].DeletionVectorFiles[0].ReferencedDataFile())
}
func TestRESTValueMapMatchesJavaContentFileParser(t *testing.T) {
@@ -364,7 +364,7 @@ func
TestDecodeScanTasksKeyMetadataMatchesJavaContentFileParser(t *testing.T) {
wire := validScanTasksWire()
// This value mirrors Java TestContentFileParser's all-optional
data-file
// fixture. SingleValueParser encodes binary values as hexadecimal
strings.
- wire.FileScanTasks[0].DataFile.KeyMetadata =
stringPtr("00000000000000000000000000000000")
+ wire.FileScanTasks[0].DataFile.KeyMetadata =
new("00000000000000000000000000000000")
tasks, err := DecodeScanTasks(wire, metadata, metadata.schema, nil)
require.NoError(t, err)
@@ -473,8 +473,8 @@ func TestDecodeScanTasksRejectsMalformedPayloads(t
*testing.T) {
mutate: func(w *ScanTasks) {
w.DeleteFiles[0].Content = "equality-deletes"
w.DeleteFiles[0].EqualityIDs = []int{1}
- w.DeleteFiles[0].ContentOffset = int64Ptr(10)
- w.DeleteFiles[0].ContentSizeInBytes =
int64Ptr(20)
+ w.DeleteFiles[0].ContentOffset = new(int64(10))
+ w.DeleteFiles[0].ContentSizeInBytes =
new(int64(20))
},
want: "must not carry position-delete reference or blob
offsets",
},
@@ -509,7 +509,7 @@ func TestDecodeScanTasksRejectsMalformedPayloads(t
*testing.T) {
{
name: "referenced data file disagrees with task",
mutate: func(w *ScanTasks) {
- w.DeleteFiles[0].ReferencedDataFile =
stringPtr("s3://bucket/table/other.parquet")
+ w.DeleteFiles[0].ReferencedDataFile =
new("s3://bucket/table/other.parquet")
w.FileScanTasks[0].DeleteFileReferences =
[]int{0}
},
want: "task data-file",
@@ -518,8 +518,8 @@ func TestDecodeScanTasksRejectsMalformedPayloads(t
*testing.T) {
name: "deletion vector referenced by different data
files",
mutate: func(w *ScanTasks) {
w.DeleteFiles[0].FileFormat = "puffin"
- w.DeleteFiles[0].ContentOffset = int64Ptr(10)
- w.DeleteFiles[0].ContentSizeInBytes =
int64Ptr(20)
+ w.DeleteFiles[0].ContentOffset = new(int64(10))
+ w.DeleteFiles[0].ContentSizeInBytes =
new(int64(20))
w.FileScanTasks[0].DeleteFileReferences =
[]int{0}
secondDataFile := *w.FileScanTasks[0].DataFile
secondDataFile.FilePath =
"s3://bucket/table/other.parquet"
@@ -692,6 +692,7 @@ func newScanTaskDecoderMetadata() *scanTaskDecoderMetadata {
func (m *scanTaskDecoderMetadata) CurrentSchema() *iceberg.Schema { return
m.schema }
func (m *scanTaskDecoderMetadata) Schemas() []*iceberg.Schema { return
[]*iceberg.Schema{m.schema} }
+
func (m *scanTaskDecoderMetadata) PartitionSpec() iceberg.PartitionSpec {
return m.spec
}
@@ -715,9 +716,6 @@ func mustLiteral(t *testing.T, value string, typ
iceberg.Type) iceberg.Literal {
return literal
}
-func intPtr(value int) *int { return &value }
-func int64Ptr(value int64) *int64 { return &value }
-
func TestPartitionDecodePlanKeepsValuesIndependent(t *testing.T) {
t.Parallel()
diff --git a/catalog/rest/wait_for_plan_test.go
b/catalog/rest/wait_for_plan_test.go
index 5035073b0..aac1bc52f 100644
--- a/catalog/rest/wait_for_plan_test.go
+++ b/catalog/rest/wait_for_plan_test.go
@@ -667,7 +667,7 @@ func TestWaitForPlanForwardsAccessDelegation(t *testing.T) {
})
_, err := cat.WaitForPlan(context.Background(), table.Identifier{"db",
"tbl"}, "plan-1", WaitForPlanOptions{
- AccessDelegation: stringPtr("remote-signing"),
+ AccessDelegation: new("remote-signing"),
})
require.NoError(t, err)
}
diff --git a/catalog/sql/sql.go b/catalog/sql/sql.go
index 61370d1c6..5a29937ab 100644
--- a/catalog/sql/sql.go
+++ b/catalog/sql/sql.go
@@ -352,8 +352,7 @@ func isRetryableSerializableError(err error) bool {
}
}
- var mysqlErr *mysql.MySQLError
- if errors.As(err, &mysqlErr) {
+ if mysqlErr, ok := errors.AsType[*mysql.MySQLError](err); ok {
switch mysqlErr.Number {
case 1205, 1213: // lock wait timeout, deadlock
return true
diff --git a/cmd/iceberg/upgrade_rollback_test.go
b/cmd/iceberg/upgrade_rollback_test.go
index 3464fb759..70d5a3279 100644
--- a/cmd/iceberg/upgrade_rollback_test.go
+++ b/cmd/iceberg/upgrade_rollback_test.go
@@ -227,7 +227,7 @@ func TestResolveRollbackSnapshotIDExplicit(t *testing.T) {
got, err := resolveRollbackSnapshotID(tbl, &RollbackCmd{
TableID: "db.events",
- SnapshotID: int64Ptr(100),
+ SnapshotID: new(int64(100)),
})
require.NoError(t, err)
@@ -332,7 +332,7 @@ func TestValidateRollbackSelector(t *testing.T) {
}{
{
name: "snapshot id only",
- cmd: RollbackCmd{SnapshotID: int64Ptr(100)},
+ cmd: RollbackCmd{SnapshotID: new(int64(100))},
wantErr: "",
},
{
@@ -342,7 +342,7 @@ func TestValidateRollbackSelector(t *testing.T) {
},
{
name: "both selectors",
- cmd: RollbackCmd{SnapshotID: int64Ptr(100),
Timestamp: "2026-01-15T03:00:00Z"},
+ cmd: RollbackCmd{SnapshotID: new(int64(100)),
Timestamp: "2026-01-15T03:00:00Z"},
wantErr: "mutually exclusive",
},
{
@@ -389,7 +389,7 @@ func TestResolveRollbackSnapshotIDErrors(t *testing.T) {
},
{
name: "missing snapshot id",
- cmd: RollbackCmd{TableID: "db.events", SnapshotID:
int64Ptr(999)},
+ cmd: RollbackCmd{TableID: "db.events", SnapshotID:
new(int64(999))},
wantErr: "snapshot 999 not found",
},
}
@@ -551,7 +551,7 @@ func TestRunRollbackRejectsNonAncestor(t *testing.T) {
exitCode := captureExit(func() {
runRollback(context.Background(), &errOut, cat, &RollbackCmd{
TableID: "db.events",
- SnapshotID: int64Ptr(300),
+ SnapshotID: new(int64(300)),
Yes: true,
})
})
@@ -575,7 +575,7 @@ func TestRunRollbackRejectsInvalidSelectorsBeforeLoad(t
*testing.T) {
name: "snapshot id and timestamp",
cmd: RollbackCmd{
TableID: "db.events",
- SnapshotID: int64Ptr(100),
+ SnapshotID: new(int64(100)),
Timestamp:
time.UnixMilli(1515100955770).UTC().Format(time.RFC3339),
},
wantErr: "mutually exclusive",
@@ -707,10 +707,6 @@ func upgradeRollbackTestTable(t *testing.T) *table.Table {
return table.New([]string{"db", "events"}, meta, "", nil, nil)
}
-func int64Ptr(v int64) *int64 {
- return &v
-}
-
type errCapture struct {
textOutput
lastErr error
diff --git a/codec/data_file_test.go b/codec/data_file_test.go
index d414254b9..3eb9ca21d 100644
--- a/codec/data_file_test.go
+++ b/codec/data_file_test.go
@@ -279,8 +279,8 @@ var expectedDataFileMethods = []string{
func dataFileInterfaceMethods() []string {
t := reflect.TypeFor[iceberg.DataFile]()
out := make([]string, 0, t.NumMethod())
- for i := range t.NumMethod() {
- out = append(out, t.Method(i).Name)
+ for method := range t.Methods() {
+ out = append(out, method.Name)
}
sort.Strings(out)
diff --git a/go.mod b/go.mod
index 525f08069..a9c93bdef 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@
module github.com/apache/iceberg-go
-go 1.25.9
+go 1.26.0
require (
cloud.google.com/go/storage v1.66.0
diff --git a/literals.go b/literals.go
index 4f6e27e07..fd3cac903 100644
--- a/literals.go
+++ b/literals.go
@@ -627,6 +627,7 @@ func (f Float32Literal) Type() Type {
return PrimitiveTypes.F
func (f Float32Literal) Value() float32 { return float32(f) }
func (f Float32Literal) Any() any { return f.Value() }
func (f Float32Literal) String() string { return
strconv.FormatFloat(float64(f), 'g', -1, 32) }
+
func (f Float32Literal) To(t Type) (Literal, error) {
switch t := t.(type) {
case Float32Type:
@@ -675,6 +676,7 @@ func (f Float64Literal) Type() Type {
return PrimitiveTypes.F
func (f Float64Literal) Value() float64 { return float64(f) }
func (f Float64Literal) Any() any { return f.Value() }
func (f Float64Literal) String() string { return
strconv.FormatFloat(float64(f), 'g', -1, 64) }
+
func (f Float64Literal) To(t Type) (Literal, error) {
switch t := t.(type) {
case Float32Type:
@@ -873,9 +875,10 @@ func (t *TimestampLiteral) UnmarshalBinary(data []byte)
error {
type TimestampNsLiteral TimestampNano
func (TimestampNsLiteral) Comparator() Comparator[TimestampNano] { return
cmp.Compare[TimestampNano] }
-func (t TimestampNsLiteral) Type() Type { return
PrimitiveTypes.TimestampNs }
-func (t TimestampNsLiteral) Value() TimestampNano { return
TimestampNano(t) }
-func (t TimestampNsLiteral) Any() any { return
t.Value() }
+
+func (t TimestampNsLiteral) Type() Type { return
PrimitiveTypes.TimestampNs }
+func (t TimestampNsLiteral) Value() TimestampNano { return TimestampNano(t) }
+func (t TimestampNsLiteral) Any() any { return t.Value() }
func (t TimestampNsLiteral) String() string {
tm := TimestampNano(t).ToTime()
diff --git a/manifest.go b/manifest.go
index 259c96457..65eb82f56 100644
--- a/manifest.go
+++ b/manifest.go
@@ -2237,7 +2237,7 @@ func (m *ManifestListWriter) AddManifests(files
[]ManifestFile) (err error) {
ErrInvalidArgument, m.version,
file.Version())
}
- wrapped := *(file.(*manifestFile))
+ wrapped := *file.(*manifestFile)
ensurePartitionList(&wrapped.PartitionList)
if m.version == 3 {
// Ref:
https://github.com/apache/iceberg/blob/ea2071568dc66148b483a82eefedcd2992b435f7/core/src/main/java/org/apache/iceberg/ManifestListWriter.java#L157-L168
diff --git a/manifest_test.go b/manifest_test.go
index 1db955fa4..a8357378c 100644
--- a/manifest_test.go
+++ b/manifest_test.go
@@ -4205,7 +4205,7 @@ func (m *ManifestTestSuite)
TestV3ManifestListRejectsV1ManifestWithUnknownRowCou
for _, tt := range tests {
m.Run(tt.name, func() {
- legacy := *(manifestFileRecordsV1[0].(*manifestFile))
+ legacy := *manifestFileRecordsV1[0].(*manifestFile)
legacy.AddedRowsCount = tt.addedRows
legacy.ExistingRowsCount = tt.existingRows
@@ -4230,7 +4230,7 @@ func (m *ManifestTestSuite)
TestV3ManifestListRejectsV1ManifestWithUnknownRowCou
}
m.Run("mixed batch failure poisons writer", func() {
- valid := *(manifestFileRecordsV1[0].(*manifestFile))
+ valid := *manifestFileRecordsV1[0].(*manifestFile)
valid.Path = "valid.avro"
unknown := valid
unknown.Path = "unknown-counts.avro"
diff --git a/name_mapping_test.go b/name_mapping_test.go
index 7e4be6bba..30da26794 100644
--- a/name_mapping_test.go
+++ b/name_mapping_test.go
@@ -26,32 +26,30 @@ import (
"github.com/stretchr/testify/require"
)
-func makeID(v int) *int { return &v }
-
var tableNameMappingNested = iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"foo"}},
- {FieldID: makeID(2), Names: []string{"bar"}},
- {FieldID: makeID(3), Names: []string{"baz"}},
+ {FieldID: new(1), Names: []string{"foo"}},
+ {FieldID: new(2), Names: []string{"bar"}},
+ {FieldID: new(3), Names: []string{"baz"}},
{
- FieldID: makeID(4), Names: []string{"qux"},
- Fields: []iceberg.MappedField{{FieldID: makeID(5), Names:
[]string{"element"}}},
+ FieldID: new(4), Names: []string{"qux"},
+ Fields: []iceberg.MappedField{{FieldID: new(5), Names:
[]string{"element"}}},
},
- {FieldID: makeID(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(7), Names: []string{"key"}},
- {FieldID: makeID(8), Names: []string{"value"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(9), Names: []string{"key"}},
- {FieldID: makeID(10), Names: []string{"value"}},
+ {FieldID: new(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(7), Names: []string{"key"}},
+ {FieldID: new(8), Names: []string{"value"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(9), Names: []string{"key"}},
+ {FieldID: new(10), Names: []string{"value"}},
}},
}},
- {FieldID: makeID(11), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(12), Names: []string{"element"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(13), Names: []string{"latitude"}},
- {FieldID: makeID(14), Names: []string{"longitude"}},
+ {FieldID: new(11), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(12), Names: []string{"element"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(13), Names: []string{"latitude"}},
+ {FieldID: new(14), Names: []string{"longitude"}},
}},
}},
- {FieldID: makeID(15), Names: []string{"person"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(16), Names: []string{"name"}},
- {FieldID: makeID(17), Names: []string{"age"}},
+ {FieldID: new(15), Names: []string{"person"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(16), Names: []string{"name"}},
+ {FieldID: new(17), Names: []string{"age"}},
}},
}
@@ -63,13 +61,13 @@ func TestJsonMappedField(t *testing.T) {
}{
{
"simple", `{"field-id": 1, "names": ["id",
"record_id"]}`,
- iceberg.MappedField{FieldID: makeID(1), Names:
[]string{"id", "record_id"}},
+ iceberg.MappedField{FieldID: new(1), Names:
[]string{"id", "record_id"}},
},
{
"with null fields", `{"field-id": 1, "names": ["id",
"record_id"], "fields": null}`,
- iceberg.MappedField{FieldID: makeID(1), Names:
[]string{"id", "record_id"}},
+ iceberg.MappedField{FieldID: new(1), Names:
[]string{"id", "record_id"}},
},
- {"no names", `{"field-id": 1, "names": []}`,
iceberg.MappedField{FieldID: makeID(1), Names: []string{}}},
+ {"no names", `{"field-id": 1, "names": []}`,
iceberg.MappedField{FieldID: new(1), Names: []string{}}},
}
for _, tt := range tests {
@@ -97,11 +95,11 @@ func TestNameMappingFromJson(t *testing.T) {
assert.Equal(t, nm, iceberg.NameMapping{
{FieldID: nil, Names: []string{"foo", "bar"}},
- {FieldID: makeID(1), Names: []string{"id", "record_id"}},
- {FieldID: makeID(2), Names: []string{"data"}},
- {FieldID: makeID(3), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(4), Names: []string{"latitude",
"lat"}},
- {FieldID: makeID(5), Names: []string{"longitude",
"long"}},
+ {FieldID: new(1), Names: []string{"id", "record_id"}},
+ {FieldID: new(2), Names: []string{"data"}},
+ {FieldID: new(3), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(4), Names: []string{"latitude", "lat"}},
+ {FieldID: new(5), Names: []string{"longitude", "long"}},
}},
})
}
@@ -111,7 +109,7 @@ func TestApplyNameMappingUsesAlias(t *testing.T) {
iceberg.NestedField{ID: 100, Name: "renamed", Type:
iceberg.PrimitiveTypes.String},
)
mapping := iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"legacy", "renamed"}},
+ {FieldID: new(1), Names: []string{"legacy", "renamed"}},
}
result, err := iceberg.ApplyNameMapping(schema, mapping)
@@ -164,39 +162,39 @@ func TestNameMappingToString(t *testing.T) {
([location] -> 3 ([lat, latitude] -> 4), ([long, longitude] -> 5))
]`, iceberg.NameMapping{
{Names: []string{"foo"}},
- {FieldID: makeID(1), Names: []string{"id", "record_id"}},
- {FieldID: makeID(2), Names: []string{"data"}},
- {FieldID: makeID(3), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(4), Names: []string{"lat",
"latitude"}},
- {FieldID: makeID(5), Names: []string{"long",
"longitude"}},
+ {FieldID: new(1), Names: []string{"id", "record_id"}},
+ {FieldID: new(2), Names: []string{"data"}},
+ {FieldID: new(3), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(4), Names: []string{"lat", "latitude"}},
+ {FieldID: new(5), Names: []string{"long", "longitude"}},
}},
}.String())
}
func TestUpdateNameMapping(t *testing.T) {
originalMapping := iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"foo"}},
- {FieldID: makeID(2), Names: []string{"bar"}},
- {FieldID: makeID(3), Names: []string{"baz"}},
- {FieldID: makeID(4), Names: []string{"qux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(5), Names: []string{"element"}},
+ {FieldID: new(1), Names: []string{"foo"}},
+ {FieldID: new(2), Names: []string{"bar"}},
+ {FieldID: new(3), Names: []string{"baz"}},
+ {FieldID: new(4), Names: []string{"qux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(5), Names: []string{"element"}},
}},
- {FieldID: makeID(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(7), Names: []string{"key"}},
- {FieldID: makeID(8), Names: []string{"value"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(9), Names: []string{"key"}},
- {FieldID: makeID(10), Names: []string{"value"}},
+ {FieldID: new(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(7), Names: []string{"key"}},
+ {FieldID: new(8), Names: []string{"value"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(9), Names: []string{"key"}},
+ {FieldID: new(10), Names: []string{"value"}},
}},
}},
- {FieldID: makeID(11), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(12), Names: []string{"element"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(13), Names:
[]string{"latitude"}},
- {FieldID: makeID(14), Names:
[]string{"longitude"}},
+ {FieldID: new(11), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(12), Names: []string{"element"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(13), Names: []string{"latitude"}},
+ {FieldID: new(14), Names:
[]string{"longitude"}},
}},
}},
- {FieldID: makeID(15), Names: []string{"person"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(16), Names: []string{"name"}},
- {FieldID: makeID(17), Names: []string{"age"}},
+ {FieldID: new(15), Names: []string{"person"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(16), Names: []string{"name"}},
+ {FieldID: new(17), Names: []string{"age"}},
}},
}
@@ -286,7 +284,7 @@ func TestUpdateNameMapping(t *testing.T) {
)
require.NoError(t, err)
assert.Equal(t, iceberg.NameMapping{{
- FieldID: makeID(1),
+ FieldID: new(1),
Names: []string{"original", "renamed"},
}}, result)
})
@@ -309,31 +307,31 @@ func TestUpdateNameMapping(t *testing.T) {
require.NoError(t, err)
expected := iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"foo",
"foo_update"}},
- {FieldID: makeID(2), Names: []string{"bar"}},
- {FieldID: makeID(3), Names: []string{"baz"}},
- {FieldID: makeID(4), Names: []string{"qux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(5), Names:
[]string{"element"}},
+ {FieldID: new(1), Names: []string{"foo", "foo_update"}},
+ {FieldID: new(2), Names: []string{"bar"}},
+ {FieldID: new(3), Names: []string{"baz"}},
+ {FieldID: new(4), Names: []string{"qux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(5), Names: []string{"element"}},
}},
- {FieldID: makeID(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(7), Names: []string{"key"}},
- {FieldID: makeID(8), Names: []string{"value"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(9), Names:
[]string{"key"}},
- {FieldID: makeID(10), Names:
[]string{"value"}},
+ {FieldID: new(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(7), Names: []string{"key"}},
+ {FieldID: new(8), Names: []string{"value"},
Fields: []iceberg.MappedField{
+ {FieldID: new(9), Names:
[]string{"key"}},
+ {FieldID: new(10), Names:
[]string{"value"}},
}},
}},
- {FieldID: makeID(11), Names: []string{"location"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(12), Names:
[]string{"element"}, Fields: []iceberg.MappedField{
- {FieldID: makeID(13), Names:
[]string{"latitude"}},
- {FieldID: makeID(14), Names:
[]string{"longitude"}},
+ {FieldID: new(11), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(12), Names: []string{"element"},
Fields: []iceberg.MappedField{
+ {FieldID: new(13), Names:
[]string{"latitude"}},
+ {FieldID: new(14), Names:
[]string{"longitude"}},
}},
}},
- {FieldID: makeID(15), Names: []string{"person"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(17), Names: []string{"age"}},
- {FieldID: makeID(19), Names: []string{"name"}},
- {FieldID: makeID(20), Names:
[]string{"add_20"}},
+ {FieldID: new(15), Names: []string{"person"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(17), Names: []string{"age"}},
+ {FieldID: new(19), Names: []string{"name"}},
+ {FieldID: new(20), Names: []string{"add_20"}},
}},
- {FieldID: makeID(18), Names: []string{"add_18"}},
+ {FieldID: new(18), Names: []string{"add_18"}},
}
assert.Equal(t, expected, result)
@@ -350,28 +348,28 @@ func TestUpdateNameMapping(t *testing.T) {
require.NoError(t, err)
expected := iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"foo", "new_foo"}},
- {FieldID: makeID(2), Names: []string{"bar", "new_bar"}},
- {FieldID: makeID(3), Names: []string{"baz"}},
- {FieldID: makeID(4), Names: []string{"qux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(5), Names:
[]string{"element"}},
+ {FieldID: new(1), Names: []string{"foo", "new_foo"}},
+ {FieldID: new(2), Names: []string{"bar", "new_bar"}},
+ {FieldID: new(3), Names: []string{"baz"}},
+ {FieldID: new(4), Names: []string{"qux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(5), Names: []string{"element"}},
}},
- {FieldID: makeID(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(7), Names: []string{"key"}},
- {FieldID: makeID(8), Names: []string{"value"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(9), Names:
[]string{"key"}},
- {FieldID: makeID(10), Names:
[]string{"value"}},
+ {FieldID: new(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(7), Names: []string{"key"}},
+ {FieldID: new(8), Names: []string{"value"},
Fields: []iceberg.MappedField{
+ {FieldID: new(9), Names:
[]string{"key"}},
+ {FieldID: new(10), Names:
[]string{"value"}},
}},
}},
- {FieldID: makeID(11), Names: []string{"location"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(12), Names:
[]string{"element"}, Fields: []iceberg.MappedField{
- {FieldID: makeID(13), Names:
[]string{"latitude"}},
- {FieldID: makeID(14), Names:
[]string{"longitude"}},
+ {FieldID: new(11), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(12), Names: []string{"element"},
Fields: []iceberg.MappedField{
+ {FieldID: new(13), Names:
[]string{"latitude"}},
+ {FieldID: new(14), Names:
[]string{"longitude"}},
}},
}},
- {FieldID: makeID(15), Names: []string{"person"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(16), Names: []string{"name"}},
- {FieldID: makeID(17), Names: []string{"age"}},
+ {FieldID: new(15), Names: []string{"person"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(16), Names: []string{"name"}},
+ {FieldID: new(17), Names: []string{"age"}},
}},
}
@@ -393,31 +391,31 @@ func TestUpdateNameMapping(t *testing.T) {
require.NoError(t, err)
expected := iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"foo"}},
- {FieldID: makeID(2), Names: []string{"bar"}},
- {FieldID: makeID(3), Names: []string{"baz"}},
- {FieldID: makeID(4), Names: []string{"qux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(5), Names:
[]string{"element"}},
+ {FieldID: new(1), Names: []string{"foo"}},
+ {FieldID: new(2), Names: []string{"bar"}},
+ {FieldID: new(3), Names: []string{"baz"}},
+ {FieldID: new(4), Names: []string{"qux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(5), Names: []string{"element"}},
}},
- {FieldID: makeID(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(7), Names: []string{"key"}},
- {FieldID: makeID(8), Names: []string{"value"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(9), Names:
[]string{"key"}},
- {FieldID: makeID(10), Names:
[]string{"value"}},
+ {FieldID: new(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(7), Names: []string{"key"}},
+ {FieldID: new(8), Names: []string{"value"},
Fields: []iceberg.MappedField{
+ {FieldID: new(9), Names:
[]string{"key"}},
+ {FieldID: new(10), Names:
[]string{"value"}},
}},
}},
- {FieldID: makeID(11), Names: []string{"location"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(12), Names:
[]string{"element"}, Fields: []iceberg.MappedField{
- {FieldID: makeID(13), Names:
[]string{"latitude"}},
- {FieldID: makeID(14), Names:
[]string{"longitude"}},
+ {FieldID: new(11), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(12), Names: []string{"element"},
Fields: []iceberg.MappedField{
+ {FieldID: new(13), Names:
[]string{"latitude"}},
+ {FieldID: new(14), Names:
[]string{"longitude"}},
}},
}},
- {FieldID: makeID(15), Names: []string{"person"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(16), Names: []string{"name"}},
- {FieldID: makeID(17), Names: []string{"age"}},
- {FieldID: makeID(22), Names: []string{"email"}},
+ {FieldID: new(15), Names: []string{"person"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(16), Names: []string{"name"}},
+ {FieldID: new(17), Names: []string{"age"}},
+ {FieldID: new(22), Names: []string{"email"}},
}},
- {FieldID: makeID(21), Names:
[]string{"new_root_field"}},
+ {FieldID: new(21), Names: []string{"new_root_field"}},
}
assert.Equal(t, expected, result)
diff --git a/partitions.go b/partitions.go
index 3cf043e18..58014bd41 100644
--- a/partitions.go
+++ b/partitions.go
@@ -230,8 +230,7 @@ func (p *PartitionField) unmarshal(b []byte, binding
specBinding) error {
func unmarshalJSONField(data json.RawMessage, field string, value any) error {
if err := json.Unmarshal(data, value); err != nil {
- var typeErr *json.UnmarshalTypeError
- if errors.As(err, &typeErr) {
+ if typeErr, ok := errors.AsType[*json.UnmarshalTypeError](err);
ok {
typeErr.Struct = ""
typeErr.Field = field
}
diff --git a/puffin/puffin_reader.go b/puffin/puffin_reader.go
index ab2c6c0e6..b858a3f78 100644
--- a/puffin/puffin_reader.go
+++ b/puffin/puffin_reader.go
@@ -509,16 +509,23 @@ func (r *Reader) readFooter() error {
// FooterPayloadSize defines a single JSON footer object. Reject
trailing
// content deliberately, even though some other Iceberg implementations
// accept padding or additional values inside the footer payload.
- if decoder.More() {
- return errors.New("puffin: unexpected content after footer
JSON")
- }
- if _, err := decoder.Token(); !errors.Is(err, io.EOF) {
+ //
+ // A failed decompression read also stops the decoder here; report that
+ // error rather than trailing content. Since Go 1.27, Decoder.More
reports
+ // true on non-EOF read errors, so both checks need it.
+ trailingContentErr := func() error {
if compressedFooter != nil && compressedFooter.err != nil {
return fmt.Errorf("puffin: read compressed footer: %w",
compressedFooter.err)
}
return errors.New("puffin: unexpected content after footer
JSON")
}
+ if decoder.More() {
+ return trailingContentErr()
+ }
+ if _, err := decoder.Token(); !errors.Is(err, io.EOF) {
+ return trailingContentErr()
+ }
if limitedFooter != nil && limitedFooter.N == 0 {
return fmt.Errorf("puffin: footer exceeds maximum size %d",
r.maxFooterSize)
}
diff --git a/table/arrow_utils.go b/table/arrow_utils.go
index c974b8d69..9173bfc15 100644
--- a/table/arrow_utils.go
+++ b/table/arrow_utils.go
@@ -662,7 +662,8 @@ func (c convertToArrow) Map(m iceberg.MapType, keyResult,
valResult arrow.Field)
}
func (c convertToArrow) Primitive(iceberg.PrimitiveType) arrow.Field {
panic("shouldn't be called") }
-func (c convertToArrow) Variant(iceberg.VariantType) arrow.Field {
panic("shouldn't be called") }
+
+func (c convertToArrow) Variant(iceberg.VariantType) arrow.Field {
panic("shouldn't be called") }
func (c convertToArrow) VisitFixed(f iceberg.FixedType) arrow.Field {
return arrow.Field{Type: &arrow.FixedSizeBinaryType{ByteWidth: f.Len()}}
diff --git a/table/arrow_utils_test.go b/table/arrow_utils_test.go
index 580847211..8eabb9e08 100644
--- a/table/arrow_utils_test.go
+++ b/table/arrow_utils_test.go
@@ -290,8 +290,6 @@ func TestArrowSchemaToIceberg(t *testing.T) {
}
}
-func makeID(v int) *int { return &v }
-
var (
icebergSchemaNested = iceberg.NewSchema(0,
iceberg.NestedField{
@@ -1103,37 +1101,37 @@ func TestArrowSchemaWithNameMapping(t *testing.T) {
err string
}{
{"simple", schemaWithoutIDs, iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"foo"}},
- {FieldID: makeID(2), Names: []string{"bar"}},
- {FieldID: makeID(3), Names: []string{"baz"}},
+ {FieldID: new(1), Names: []string{"foo"}},
+ {FieldID: new(2), Names: []string{"bar"}},
+ {FieldID: new(3), Names: []string{"baz"}},
}, icebergSchemaSimple, ""},
{"field missing", schemaWithoutIDs, iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"foo"}},
+ {FieldID: new(1), Names: []string{"foo"}},
}, nil, "field missing from name mapping: bar"},
{"nested schema", schemaNestedWithoutIDs, iceberg.NameMapping{
- {FieldID: makeID(1), Names: []string{"foo"}},
- {FieldID: makeID(2), Names: []string{"bar"}},
- {FieldID: makeID(3), Names: []string{"baz"}},
+ {FieldID: new(1), Names: []string{"foo"}},
+ {FieldID: new(2), Names: []string{"bar"}},
+ {FieldID: new(3), Names: []string{"baz"}},
{
- FieldID: makeID(4), Names: []string{"qux"},
- Fields: []iceberg.MappedField{{FieldID:
makeID(5), Names: []string{"element"}}},
- },
- {FieldID: makeID(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
- {FieldID: makeID(7), Names: []string{"key"}},
- {FieldID: makeID(8), Names: []string{"value"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(9), Names:
[]string{"key"}},
- {FieldID: makeID(10), Names:
[]string{"value"}},
+ FieldID: new(4), Names: []string{"qux"},
+ Fields: []iceberg.MappedField{{FieldID: new(5),
Names: []string{"element"}}},
+ },
+ {FieldID: new(6), Names: []string{"quux"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(7), Names: []string{"key"}},
+ {FieldID: new(8), Names: []string{"value"},
Fields: []iceberg.MappedField{
+ {FieldID: new(9), Names:
[]string{"key"}},
+ {FieldID: new(10), Names:
[]string{"value"}},
}},
}},
- {FieldID: makeID(11), Names: []string{"location"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(12), Names:
[]string{"element"}, Fields: []iceberg.MappedField{
- {FieldID: makeID(13), Names:
[]string{"latitude"}},
- {FieldID: makeID(14), Names:
[]string{"longitude"}},
+ {FieldID: new(11), Names: []string{"location"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(12), Names: []string{"element"},
Fields: []iceberg.MappedField{
+ {FieldID: new(13), Names:
[]string{"latitude"}},
+ {FieldID: new(14), Names:
[]string{"longitude"}},
}},
}},
- {FieldID: makeID(15), Names: []string{"person"},
Fields: []iceberg.MappedField{
- {FieldID: makeID(16), Names: []string{"name"}},
- {FieldID: makeID(17), Names: []string{"age"}},
+ {FieldID: new(15), Names: []string{"person"}, Fields:
[]iceberg.MappedField{
+ {FieldID: new(16), Names: []string{"name"}},
+ {FieldID: new(17), Names: []string{"age"}},
}},
}, icebergSchemaNested, ""},
}
diff --git a/table/dv/deletion_vector_bench_test.go
b/table/dv/deletion_vector_bench_test.go
index f752273c5..f07b1318d 100644
--- a/table/dv/deletion_vector_bench_test.go
+++ b/table/dv/deletion_vector_bench_test.go
@@ -138,7 +138,7 @@ func benchmarkDVFiles(b *testing.B, numDVs int)
[]iceberg.DataFile {
offset, size := meta.Offset, meta.Length
file := newDVTestFile(path, 1, &offset, &size)
- file.referencedDataFile = strPtr(referencedDataFile)
+ file.referencedDataFile = new(referencedDataFile)
files[i] = file
}
diff --git a/table/dv/deletion_vector_test.go b/table/dv/deletion_vector_test.go
index bd9814e65..7192b1238 100644
--- a/table/dv/deletion_vector_test.go
+++ b/table/dv/deletion_vector_test.go
@@ -71,8 +71,6 @@ func (*mockDVFile) SortOrderID() *int
{ return nil }
func (*mockDVFile) SpecID() int32 { return 0 }
func (*mockDVFile) FirstRowID() *int64 { return nil }
-func strPtr(s string) *string { return &s }
-
func readDVTestData(t *testing.T, name string) []byte {
t.Helper()
data, err := os.ReadFile(filepath.Join("testdata", "deletes", name))
@@ -252,7 +250,7 @@ func newDVTestFile(path string, count int64, offset, size
*int64) *mockDVFile {
path: path,
format: iceberg.PuffinFile,
count: count,
- referencedDataFile: strPtr("s3://bucket/data/data-001.parquet"),
+ referencedDataFile: new("s3://bucket/data/data-001.parquet"),
contentOffset: offset,
contentSizeInBytes: size,
}
@@ -592,7 +590,7 @@ func TestReadDVs(t *testing.T) {
for i, meta := range metas {
offset, size := meta.Offset, meta.Length
file := newDVTestFile(path, 5, &offset, &size)
- file.referencedDataFile =
strPtr(fmt.Sprintf("s3://bucket/data/data-%03d.parquet", i+1))
+ file.referencedDataFile =
new(fmt.Sprintf("s3://bucket/data/data-%03d.parquet", i+1))
files[i] = file
}
@@ -624,7 +622,7 @@ func TestReadDVs(t *testing.T) {
t.Run("invalid blob identity", func(t *testing.T) {
first := files[0].(*mockDVFile)
second := *files[1].(*mockDVFile)
- second.referencedDataFile =
strPtr("s3://bucket/data/wrong.parquet")
+ second.referencedDataFile =
new("s3://bucket/data/wrong.parquet")
_, err := ReadDVs(iceio.LocalFS{}, []iceberg.DataFile{first,
&second})
require.ErrorIs(t, err, ErrInvalidDeletionVector)
@@ -667,8 +665,8 @@ func TestReadDVsCoalescesAdjacentBlobReads(t *testing.T) {
newDVTestFile(path, 1, &secondOffset, &secondSize),
newDVTestFile(path, 1, &firstOffset, &firstSize),
}
- files[0].(*mockDVFile).referencedDataFile = strPtr("data-002.parquet")
- files[1].(*mockDVFile).referencedDataFile = strPtr("data-001.parquet")
+ files[0].(*mockDVFile).referencedDataFile = new("data-002.parquet")
+ files[1].(*mockDVFile).referencedDataFile = new("data-001.parquet")
fs := &countingReadIO{base: iceio.LocalFS{}}
bitmaps, err := ReadDVs(fs, files)
@@ -709,7 +707,7 @@ func TestReadDVsDoesNotCoalesceRangesOverSizeLimit(t
*testing.T) {
for i, meta := range metas {
offset, size := meta.Offset, meta.Length
file := newDVTestFile(path, cardinality, &offset, &size)
- file.referencedDataFile =
strPtr(fmt.Sprintf("data-%03d.parquet", i+1))
+ file.referencedDataFile = new(fmt.Sprintf("data-%03d.parquet",
i+1))
files[i] = file
}
@@ -757,7 +755,7 @@ func TestReadDVsDoesNotCoalesceBlobsWithGaps(t *testing.T) {
for i, meta := range metas {
offset, size := meta.Offset, meta.Length
file := newDVTestFile(path, 1, &offset, &size)
- file.referencedDataFile =
strPtr(fmt.Sprintf("data-%03d.parquet", i+1))
+ file.referencedDataFile = new(fmt.Sprintf("data-%03d.parquet",
i+1))
files[i] = file
}
@@ -833,7 +831,7 @@ func TestReadDVMissingReferencedDataFile(t *testing.T) {
referenced *string
}{
{name: "nil", referenced: nil},
- {name: "empty", referenced: strPtr("")},
+ {name: "empty", referenced: new("")},
} {
t.Run(tt.name, func(t *testing.T) {
offset, size := int64(4), int64(50)
diff --git a/table/dv_scan_planning_test.go b/table/dv_scan_planning_test.go
index 86a4cea49..36d55f953 100644
--- a/table/dv_scan_planning_test.go
+++ b/table/dv_scan_planning_test.go
@@ -38,9 +38,6 @@ func (d *dvMockDataFile) ReferencedDataFile() *string {
return d.referencedDataF
func (d *dvMockDataFile) ContentOffset() *int64 { return d.contentOffset
}
func (d *dvMockDataFile) ContentSizeInBytes() *int64 { return
d.contentSizeInBytes }
-func strPtr(s string) *string { return &s }
-func int64Ptr(v int64) *int64 { return &v }
-
func TestIsDeletionVector(t *testing.T) {
tests := []struct {
name string
@@ -71,9 +68,9 @@ func TestIsDeletionVector(t *testing.T) {
contentType:
iceberg.EntryContentPosDeletes,
format: iceberg.PuffinFile,
},
- referencedDataFile:
strPtr("s3://bucket/data/file.parquet"),
- contentOffset: int64Ptr(100),
- contentSizeInBytes: int64Ptr(256),
+ referencedDataFile:
new("s3://bucket/data/file.parquet"),
+ contentOffset: new(int64(100)),
+ contentSizeInBytes: new(int64(256)),
},
expected: true,
},
@@ -116,9 +113,9 @@ func TestManifestEntries_DVClassification(t *testing.T) {
contentType: iceberg.EntryContentPosDeletes,
format: iceberg.PuffinFile,
},
- referencedDataFile: strPtr("s3://bucket/data/data-001.parquet"),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile: new("s3://bucket/data/data-001.parquet"),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
}
// Equality delete entry
@@ -220,9 +217,9 @@ func TestManifestEntries_ConcurrentMerge(t *testing.T) {
contentType: iceberg.EntryContentPosDeletes,
format: iceberg.PuffinFile,
},
- referencedDataFile:
strPtr("s3://bucket/data/data-001.parquet"),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile:
new("s3://bucket/data/data-001.parquet"),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
}),
}
@@ -251,9 +248,9 @@ func TestDVMatchingToDataFiles(t *testing.T) {
path: "s3://bucket/data/dv-001.puffin",
contentType: iceberg.EntryContentPosDeletes,
},
- referencedDataFile: strPtr(dataFilePath),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile: new(dataFilePath),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
}
dvForData2 := &dvMockDataFile{
@@ -261,9 +258,9 @@ func TestDVMatchingToDataFiles(t *testing.T) {
path: "s3://bucket/data/dv-002.puffin",
contentType: iceberg.EntryContentPosDeletes,
},
- referencedDataFile: strPtr(otherDataFilePath),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(64),
+ referencedDataFile: new(otherDataFilePath),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(64)),
}
snapshotID := int64(1)
@@ -301,9 +298,9 @@ func TestDVMatchingNoMatch(t *testing.T) {
path: "s3://bucket/data/dv-001.puffin",
contentType: iceberg.EntryContentPosDeletes,
},
- referencedDataFile: strPtr("s3://bucket/data/data-999.parquet"),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile: new("s3://bucket/data/data-999.parquet"),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
}
dvEntries := []iceberg.ManifestEntry{
@@ -329,9 +326,9 @@ func TestBuildDVIndex_RejectsMultipleDVsPerDataFile(t
*testing.T) {
path: "s3://bucket/data/dv-001.puffin",
contentType: iceberg.EntryContentPosDeletes,
},
- referencedDataFile: strPtr(dataFilePath),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile: new(dataFilePath),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
}
dv2 := &dvMockDataFile{
@@ -339,9 +336,9 @@ func TestBuildDVIndex_RejectsMultipleDVsPerDataFile(t
*testing.T) {
path: "s3://bucket/data/dv-002.puffin",
contentType: iceberg.EntryContentPosDeletes,
},
- referencedDataFile: strPtr(dataFilePath),
- contentOffset: int64Ptr(256),
- contentSizeInBytes: int64Ptr(64),
+ referencedDataFile: new(dataFilePath),
+ contentOffset: new(int64(256)),
+ contentSizeInBytes: new(int64(64)),
}
dvEntries := []iceberg.ManifestEntry{
@@ -364,9 +361,9 @@ func TestMatchDVToData_SequenceNumberGuard(t *testing.T) {
path: "s3://bucket/data/dv-001.puffin",
contentType: iceberg.EntryContentPosDeletes,
},
- referencedDataFile: strPtr(dataFilePath),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile: new(dataFilePath),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
}
dvSeqNum := int64(5)
@@ -420,10 +417,10 @@ func TestMatchDVToData_NilDVSequenceNumber(t *testing.T) {
dataSeq *int64 // nil → unset
expectDV bool
}{
- {"unset DV seq, real data seq — applies (regression)", nil,
int64Ptr(7), true},
+ {"unset DV seq, real data seq — applies (regression)", nil,
new(int64(7)), true},
{"unset DV seq and unset data seq — applies", nil, nil, true},
- {"known DV seq 0, newer data — skipped (guard stays tight)",
int64Ptr(0), int64Ptr(5), false},
- {"known DV seq 0, same data seq 0 — applies", int64Ptr(0),
int64Ptr(0), true},
+ {"known DV seq 0, newer data — skipped (guard stays tight)",
new(int64(0)), new(int64(5)), false},
+ {"known DV seq 0, same data seq 0 — applies", new(int64(0)),
new(int64(0)), true},
}
for _, tt := range tests {
@@ -433,9 +430,9 @@ func TestMatchDVToData_NilDVSequenceNumber(t *testing.T) {
path:
"s3://bucket/data/dv-001.puffin",
contentType:
iceberg.EntryContentPosDeletes,
},
- referencedDataFile: strPtr(dataFilePath),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile: new(dataFilePath),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
}
dvEntries := []iceberg.ManifestEntry{
iceberg.NewManifestEntry(iceberg.EntryStatusADDED, &snapshotID, tt.dvSeq, nil,
dvFile),
@@ -470,9 +467,9 @@ func TestFileScanTask_DeletionVectorFilesField(t
*testing.T) {
contentType: iceberg.EntryContentPosDeletes,
format: iceberg.PuffinFile,
},
- referencedDataFile: strPtr("s3://bucket/data/data-001.parquet"),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile: new("s3://bucket/data/data-001.parquet"),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
}
task := FileScanTask{
diff --git a/table/dv_scanner_read_test.go b/table/dv_scanner_read_test.go
index c466e3d30..ab94fba93 100644
--- a/table/dv_scanner_read_test.go
+++ b/table/dv_scanner_read_test.go
@@ -96,9 +96,9 @@ func newDVMockDataFile(puffinPath, referencedDataFile string,
offset, contentSiz
format: iceberg.PuffinFile,
count: recordCount,
},
- referencedDataFile: strPtr(referencedDataFile),
- contentOffset: int64Ptr(offset),
- contentSizeInBytes: int64Ptr(contentSize),
+ referencedDataFile: new(referencedDataFile),
+ contentOffset: new(offset),
+ contentSizeInBytes: new(contentSize),
}
}
@@ -223,9 +223,9 @@ func TestLazyDeletionVectorLoaderReadPath(t *testing.T) {
contentType: iceberg.EntryContentPosDeletes,
format: iceberg.PuffinFile,
},
- referencedDataFile:
strPtr("file:///table/data/data.parquet"),
+ referencedDataFile:
new("file:///table/data/data.parquet"),
contentOffset: nil,
- contentSizeInBytes: int64Ptr(42),
+ contentSizeInBytes: new(int64(42)),
}
_, err := newLazyDeletionVectorLoader(fs, []FileScanTask{{
@@ -254,8 +254,8 @@ func TestLazyDeletionVectorLoaderReadPath(t *testing.T) {
contentType: iceberg.EntryContentPosDeletes,
format: iceberg.PuffinFile,
},
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(0),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(0)),
}
var err error
diff --git a/table/incremental_append_scan_test.go
b/table/incremental_append_scan_test.go
index e883b1484..a6ace522b 100644
--- a/table/incremental_append_scan_test.go
+++ b/table/incremental_append_scan_test.go
@@ -384,7 +384,7 @@ func incrementalAppendTestTable(t *testing.T) *Table {
txn.meta.snapshotList = []Snapshot{
{SnapshotID: 1, TimestampMs: 1000, ManifestList:
"mem://default/table-location/metadata/snap-1.avro", SequenceNumber: 1,
SchemaID: &schema.ID, Summary: &Summary{Operation: OpAppend}},
- {SnapshotID: 2, ParentSnapshotID: int64Ptr(1), TimestampMs:
2000, ManifestList: "mem://default/table-location/metadata/snap-2.avro",
SequenceNumber: 2, SchemaID: &schema.ID, Summary: &Summary{Operation:
OpAppend}},
+ {SnapshotID: 2, ParentSnapshotID: new(int64(1)), TimestampMs:
2000, ManifestList: "mem://default/table-location/metadata/snap-2.avro",
SequenceNumber: 2, SchemaID: &schema.ID, Summary: &Summary{Operation:
OpAppend}},
}
txn.meta.snapshotLog = []SnapshotLogEntry{
{SnapshotID: 1, TimestampMs: 1000},
@@ -461,8 +461,8 @@ func incrementalAppendMixedOperationTable(t *testing.T)
*Table {
txn.meta.snapshotList = []Snapshot{
{SnapshotID: 1, TimestampMs: 1000, ManifestList: listAPath,
SequenceNumber: 1, SchemaID: &schema.ID, Summary: &Summary{Operation:
OpAppend}},
- {SnapshotID: 2, ParentSnapshotID: int64Ptr(1), TimestampMs:
2000, ManifestList: listBPath, SequenceNumber: 2, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpOverwrite}},
- {SnapshotID: 3, ParentSnapshotID: int64Ptr(2), TimestampMs:
3000, ManifestList: listCPath, SequenceNumber: 3, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 2, ParentSnapshotID: new(int64(1)), TimestampMs:
2000, ManifestList: listBPath, SequenceNumber: 2, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpOverwrite}},
+ {SnapshotID: 3, ParentSnapshotID: new(int64(2)), TimestampMs:
3000, ManifestList: listCPath, SequenceNumber: 3, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
}
txn.meta.snapshotLog = []SnapshotLogEntry{
{SnapshotID: 1, TimestampMs: 1000},
@@ -532,8 +532,8 @@ func incrementalAppendDivergentTable(t *testing.T) *Table {
snapshots := []*Snapshot{
{SnapshotID: 10, TimestampMs: baseTimestamp + 1,
SequenceNumber: 1, Summary: &Summary{Operation: OpAppend}},
{SnapshotID: 20, TimestampMs: baseTimestamp + 2,
SequenceNumber: 2, Summary: &Summary{Operation: OpAppend}},
- {SnapshotID: 21, ParentSnapshotID: int64Ptr(20), TimestampMs:
baseTimestamp + 3, SequenceNumber: 3, Summary: &Summary{Operation: OpAppend}},
- {SnapshotID: 22, ParentSnapshotID: int64Ptr(21), TimestampMs:
baseTimestamp + 4, SequenceNumber: 4, Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 21, ParentSnapshotID: new(int64(20)), TimestampMs:
baseTimestamp + 3, SequenceNumber: 3, Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 22, ParentSnapshotID: new(int64(21)), TimestampMs:
baseTimestamp + 4, SequenceNumber: 4, Summary: &Summary{Operation: OpAppend}},
}
for _, snapshot := range snapshots {
require.NoError(t, builder.AddSnapshot(snapshot))
@@ -615,7 +615,7 @@ func incrementalAppendExpiredExclusiveTable(t *testing.T)
*Table {
},
{
SnapshotID: 3,
- ParentSnapshotID: int64Ptr(2),
+ ParentSnapshotID: new(int64(2)),
TimestampMs: 3000,
ManifestList: manifestListCPath,
SequenceNumber: 3,
diff --git a/table/incremental_changelog_scan_test.go
b/table/incremental_changelog_scan_test.go
index 75c960e38..f94e67f09 100644
--- a/table/incremental_changelog_scan_test.go
+++ b/table/incremental_changelog_scan_test.go
@@ -463,8 +463,8 @@ func incrementalChangelogDivergentTable(t *testing.T)
*Table {
baseTimestamp := base.LastUpdatedMillis()
snapshots := []*Snapshot{
{SnapshotID: 1, TimestampMs: baseTimestamp + 1, SequenceNumber:
1, Summary: &Summary{Operation: OpAppend}},
- {SnapshotID: 2, ParentSnapshotID: int64Ptr(1), TimestampMs:
baseTimestamp + 2, SequenceNumber: 2, Summary: &Summary{Operation: OpAppend}},
- {SnapshotID: 3, ParentSnapshotID: int64Ptr(1), TimestampMs:
baseTimestamp + 3, SequenceNumber: 3, Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 2, ParentSnapshotID: new(int64(1)), TimestampMs:
baseTimestamp + 2, SequenceNumber: 2, Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 3, ParentSnapshotID: new(int64(1)), TimestampMs:
baseTimestamp + 3, SequenceNumber: 3, Summary: &Summary{Operation: OpAppend}},
}
for _, snapshot := range snapshots {
require.NoError(t, builder.AddSnapshot(snapshot))
@@ -555,9 +555,9 @@ func incrementalChangelogTestTable(t *testing.T) *Table {
txn.meta.snapshotList = []Snapshot{
{SnapshotID: 1, TimestampMs: 1000, ManifestList: listOnePath,
SequenceNumber: 1, SchemaID: &schema.ID, Summary: &Summary{Operation:
OpAppend}},
- {SnapshotID: 2, ParentSnapshotID: int64Ptr(1), TimestampMs:
2000, ManifestList: listTwoPath, SequenceNumber: 2, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpOverwrite}},
- {SnapshotID: 3, ParentSnapshotID: int64Ptr(2), TimestampMs:
3000, ManifestList: listThreePath, SequenceNumber: 3, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpReplace}},
- {SnapshotID: 4, ParentSnapshotID: int64Ptr(3), TimestampMs:
4000, ManifestList: listFourPath, SequenceNumber: 4, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 2, ParentSnapshotID: new(int64(1)), TimestampMs:
2000, ManifestList: listTwoPath, SequenceNumber: 2, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpOverwrite}},
+ {SnapshotID: 3, ParentSnapshotID: new(int64(2)), TimestampMs:
3000, ManifestList: listThreePath, SequenceNumber: 3, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpReplace}},
+ {SnapshotID: 4, ParentSnapshotID: new(int64(3)), TimestampMs:
4000, ManifestList: listFourPath, SequenceNumber: 4, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
}
txn.meta.snapshotLog = []SnapshotLogEntry{
{SnapshotID: 1, TimestampMs: 1000},
@@ -659,9 +659,9 @@ func incrementalChangelogManifestRewriteTable(t *testing.T)
*Table {
txn.meta.snapshotList = []Snapshot{
{SnapshotID: 1, TimestampMs: 1000, ManifestList: listOnePath,
SequenceNumber: 1, SchemaID: &schema.ID, Summary: &Summary{Operation:
OpAppend}},
- {SnapshotID: 2, ParentSnapshotID: int64Ptr(1), TimestampMs:
2000, ManifestList: listTwoPath, SequenceNumber: 2, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
- {SnapshotID: 3, ParentSnapshotID: int64Ptr(2), TimestampMs:
3000, ManifestList: listThreePath, SequenceNumber: 3, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpReplace}},
- {SnapshotID: 4, ParentSnapshotID: int64Ptr(3), TimestampMs:
4000, ManifestList: listFourPath, SequenceNumber: 4, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 2, ParentSnapshotID: new(int64(1)), TimestampMs:
2000, ManifestList: listTwoPath, SequenceNumber: 2, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 3, ParentSnapshotID: new(int64(2)), TimestampMs:
3000, ManifestList: listThreePath, SequenceNumber: 3, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpReplace}},
+ {SnapshotID: 4, ParentSnapshotID: new(int64(3)), TimestampMs:
4000, ManifestList: listFourPath, SequenceNumber: 4, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
}
txn.meta.snapshotLog = []SnapshotLogEntry{
{SnapshotID: 1, TimestampMs: 1000},
@@ -750,8 +750,8 @@ func incrementalChangelogDeleteManifestTable(t *testing.T)
*Table {
txn.meta.snapshotList = []Snapshot{
{SnapshotID: 1, TimestampMs: 1000, ManifestList: listOnePath,
SequenceNumber: 1, SchemaID: &schema.ID, Summary: &Summary{Operation:
OpAppend}},
- {SnapshotID: 2, ParentSnapshotID: int64Ptr(1), TimestampMs:
2000, ManifestList: listTwoPath, SequenceNumber: 2, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpDelete}},
- {SnapshotID: 3, ParentSnapshotID: int64Ptr(2), TimestampMs:
3000, ManifestList: listThreePath, SequenceNumber: 3, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
+ {SnapshotID: 2, ParentSnapshotID: new(int64(1)), TimestampMs:
2000, ManifestList: listTwoPath, SequenceNumber: 2, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpDelete}},
+ {SnapshotID: 3, ParentSnapshotID: new(int64(2)), TimestampMs:
3000, ManifestList: listThreePath, SequenceNumber: 3, SchemaID: &schema.ID,
Summary: &Summary{Operation: OpAppend}},
}
txn.meta.snapshotLog = []SnapshotLogEntry{
{SnapshotID: 1, TimestampMs: 1000},
diff --git a/table/inspect_internal_test.go b/table/inspect_internal_test.go
index 57c992cd6..55de0c4cf 100644
--- a/table/inspect_internal_test.go
+++ b/table/inspect_internal_test.go
@@ -92,8 +92,8 @@ func inspectTestTable(identifier Identifier, snapshotRefs
map[string]SnapshotRef
Props: iceberg.Properties{},
SnapshotList: []Snapshot{
{SnapshotID: s1, TimestampMs: 1100, ManifestList:
"/snap-101.avro"},
- {SnapshotID: s2, ParentSnapshotID: int64Ptr(s1),
TimestampMs: 1200, ManifestList: "/snap-102.avro"},
- {SnapshotID: s3, ParentSnapshotID: int64Ptr(s1),
TimestampMs: 1300, ManifestList: "/snap-103.avro"},
+ {SnapshotID: s2, ParentSnapshotID: new(s1),
TimestampMs: 1200, ManifestList: "/snap-102.avro"},
+ {SnapshotID: s3, ParentSnapshotID: new(s1),
TimestampMs: 1300, ManifestList: "/snap-103.avro"},
},
CurrentSnapshotID: ¤t,
SnapshotLog: []SnapshotLogEntry{
@@ -514,7 +514,7 @@ func snapshotsTestTable() *Table {
},
},
// s2 intentionally carries no summary and no
manifest-list path.
- {SnapshotID: s2, ParentSnapshotID: int64Ptr(s1),
TimestampMs: 1200},
+ {SnapshotID: s2, ParentSnapshotID: new(s1),
TimestampMs: 1200},
},
CurrentSnapshotID: ¤t,
SortOrderList: []SortOrder{UnsortedSortOrder},
@@ -948,7 +948,7 @@ func TestInspectDeleteFiles(t *testing.T) {
entry := func(status iceberg.ManifestEntryStatus, file
iceberg.DataFile) iceberg.ManifestEntry {
sequenceNumber := int64(1)
- return iceberg.NewManifestEntry(status, int64Ptr(snapshotID),
&sequenceNumber, &sequenceNumber, file)
+ return iceberg.NewManifestEntry(status, new(snapshotID),
&sequenceNumber, &sequenceNumber, file)
}
tbl := inspectFilesTableWithManifests(t, spec,
inspectManifestSpec{
@@ -1312,7 +1312,7 @@ func TestInspectManifests(t *testing.T) {
"mem://default/table-location/data/data.parquet",
map[int]any{1000: int32(7)}, 3)
sequenceNumber := int64(1)
entry := iceberg.NewManifestEntry(
- iceberg.EntryStatusADDED, int64Ptr(snapshotID),
&sequenceNumber, &sequenceNumber, file)
+ iceberg.EntryStatusADDED, new(snapshotID), &sequenceNumber,
&sequenceNumber, file)
manifestPath :=
"mem://default/table-location/metadata/data-manifest.avro"
manifestListPath :=
"mem://default/table-location/metadata/snap-1-manifest-list.avro"
@@ -1999,7 +1999,7 @@ func inspectDataFileEntries(t *testing.T, spec
iceberg.PartitionSpec, count int)
file := newTestDataFile(t, spec, path, nil)
sequenceNumber := int64(1)
entries = append(entries, iceberg.NewManifestEntry(
- iceberg.EntryStatusADDED, int64Ptr(snapshotID),
&sequenceNumber, &sequenceNumber, file))
+ iceberg.EntryStatusADDED, new(snapshotID),
&sequenceNumber, &sequenceNumber, file))
}
return entries
@@ -2340,13 +2340,13 @@ func
TestInspectDataFilesStreamsBatchesAndSkipsDeleted(t *testing.T) {
"mem://default/table-location/data/live-"+strconv.Itoa(index)+".parquet", nil)
sequenceNumber := int64(1)
entries = append(entries, iceberg.NewManifestEntry(
- iceberg.EntryStatusADDED, int64Ptr(snapshotID),
&sequenceNumber, &sequenceNumber, file))
+ iceberg.EntryStatusADDED, new(snapshotID),
&sequenceNumber, &sequenceNumber, file))
}
deletedPath := "mem://default/table-location/data/deleted.parquet"
deleted := newTestDataFile(t, spec, deletedPath, nil)
deletedSequenceNumber := int64(1)
entries = append(entries, iceberg.NewManifestEntry(
- iceberg.EntryStatusDELETED, int64Ptr(snapshotID),
&deletedSequenceNumber, &deletedSequenceNumber, deleted))
+ iceberg.EntryStatusDELETED, new(snapshotID),
&deletedSequenceNumber, &deletedSequenceNumber, deleted))
manifestPath :=
"mem://default/table-location/metadata/data-manifest.avro"
manifestListPath :=
"mem://default/table-location/metadata/snap-1-manifest-list.avro"
@@ -2400,7 +2400,7 @@ func TestInspectDataFilesReturnsPartitionValues(t
*testing.T) {
"mem://default/table-location/data/partitioned.parquet",
map[int]any{1000: int32(7)})
sequenceNumber := int64(1)
entry := iceberg.NewManifestEntry(
- iceberg.EntryStatusADDED, int64Ptr(snapshotID),
&sequenceNumber, &sequenceNumber, file)
+ iceberg.EntryStatusADDED, new(snapshotID), &sequenceNumber,
&sequenceNumber, file)
tbl := inspectDataFilesTable(t, spec, []iceberg.ManifestEntry{entry})
rr, err := tbl.Inspect().DataFiles(context.Background())
@@ -2423,7 +2423,7 @@ func
TestInspectDataFilesEmitsEmptyBatchWhenAllEntriesAreDeleted(t *testing.T) {
"mem://default/table-location/data/deleted.parquet", nil)
sequenceNumber := int64(1)
entry := iceberg.NewManifestEntry(
- iceberg.EntryStatusDELETED, int64Ptr(snapshotID),
&sequenceNumber, &sequenceNumber, file)
+ iceberg.EntryStatusDELETED, new(snapshotID), &sequenceNumber,
&sequenceNumber, file)
tbl := inspectDataFilesTable(t, spec, []iceberg.ManifestEntry{entry})
rr, err := tbl.Inspect().DataFiles(context.Background())
@@ -2764,7 +2764,7 @@ func TestInspectPartitionsAggregatesDataAndDeletes(t
*testing.T) {
dataEntries := make([]iceberg.ManifestEntry, 0, len(dataFiles))
for _, file := range dataFiles {
dataEntries = append(dataEntries, iceberg.NewManifestEntry(
- iceberg.EntryStatusADDED, int64Ptr(snapshotID),
&dataSequenceNumber, &dataSequenceNumber, file))
+ iceberg.EntryStatusADDED, new(snapshotID),
&dataSequenceNumber, &dataSequenceNumber, file))
}
dataManifestPath :=
"mem://default/table-location/metadata/data-manifest.avro"
@@ -2795,9 +2795,9 @@ func TestInspectPartitionsAggregatesDataAndDeletes(t
*testing.T) {
iceberg.WithManifestWriterContent(iceberg.ManifestContentDeletes))
require.NoError(t, err)
require.NoError(t, deleteWriter.Add(iceberg.NewManifestEntry(
- iceberg.EntryStatusADDED, int64Ptr(snapshotID),
&dataSequenceNumber, &dataSequenceNumber, deleteFile)))
+ iceberg.EntryStatusADDED, new(snapshotID), &dataSequenceNumber,
&dataSequenceNumber, deleteFile)))
require.NoError(t, deleteWriter.Add(iceberg.NewManifestEntry(
- iceberg.EntryStatusADDED, int64Ptr(snapshotID),
&dataSequenceNumber, &dataSequenceNumber, equalityDeleteFile)))
+ iceberg.EntryStatusADDED, new(snapshotID), &dataSequenceNumber,
&dataSequenceNumber, equalityDeleteFile)))
require.NoError(t, deleteWriter.Close())
deleteManifest, err := deleteWriter.ToManifestFile(deleteManifestPath,
int64(deleteManifestBuf.Len()),
iceberg.WithManifestFileContent(iceberg.ManifestContentDeletes))
@@ -2817,7 +2817,7 @@ func TestInspectPartitionsAggregatesDataAndDeletes(t
*testing.T) {
SequenceNumber: manifestListSequenceNumber,
TimestampMs: 2000,
}}
- txn.meta.currentSnapshotID = int64Ptr(snapshotID)
+ txn.meta.currentSnapshotID = new(snapshotID)
built, err := txn.meta.Build()
require.NoError(t, err)
@@ -2862,7 +2862,7 @@ func
TestInspectPartitionsLeavesSpecIDUnsetForExpiredSnapshot(t *testing.T) {
var manifestBuf bytes.Buffer
_, err := iceberg.WriteManifest(manifestPath, &manifestBuf, 2, spec,
schema, expiredSnapshotID,
[]iceberg.ManifestEntry{iceberg.NewManifestEntry(
- iceberg.EntryStatusADDED, int64Ptr(expiredSnapshotID),
&sequenceNumber, &sequenceNumber, file)})
+ iceberg.EntryStatusADDED, new(expiredSnapshotID),
&sequenceNumber, &sequenceNumber, file)})
require.NoError(t, err)
require.NoError(t, memIO.WriteFile(manifestPath, manifestBuf.Bytes()))
manifest := iceberg.NewManifestFile(2, manifestPath,
int64(manifestBuf.Len()), int32(spec.ID()), expiredSnapshotID).
@@ -2884,7 +2884,7 @@ func
TestInspectPartitionsLeavesSpecIDUnsetForExpiredSnapshot(t *testing.T) {
SequenceNumber: currentSequenceNumber,
TimestampMs: 2000,
}}
- txn.meta.currentSnapshotID = int64Ptr(currentSnapshotID)
+ txn.meta.currentSnapshotID = new(currentSnapshotID)
built, err := txn.meta.Build()
require.NoError(t, err)
@@ -2952,8 +2952,8 @@ func TestInspectEntriesIncludesDeletedEntries(t
*testing.T) {
"mem://default/table-location/data/deleted.parquet", nil)
sequenceNumber := int64(1)
entries := []iceberg.ManifestEntry{
- iceberg.NewManifestEntry(iceberg.EntryStatusADDED,
int64Ptr(snapshotID), &sequenceNumber, &sequenceNumber, addedFile),
- iceberg.NewManifestEntry(iceberg.EntryStatusDELETED,
int64Ptr(snapshotID), &sequenceNumber, &sequenceNumber, deletedFile),
+ iceberg.NewManifestEntry(iceberg.EntryStatusADDED,
new(snapshotID), &sequenceNumber, &sequenceNumber, addedFile),
+ iceberg.NewManifestEntry(iceberg.EntryStatusDELETED,
new(snapshotID), &sequenceNumber, &sequenceNumber, deletedFile),
}
manifestPath :=
"mem://default/table-location/metadata/data-manifest.avro"
@@ -2973,7 +2973,7 @@ func TestInspectEntriesIncludesDeletedEntries(t
*testing.T) {
ManifestList: manifestListPath,
SequenceNumber: sequenceNumber,
}}
- txn.meta.currentSnapshotID = int64Ptr(snapshotID)
+ txn.meta.currentSnapshotID = new(snapshotID)
built, err := txn.meta.Build()
require.NoError(t, err)
diff --git a/table/metadata_builder_internal_test.go
b/table/metadata_builder_internal_test.go
index 64b1135d9..b0a881249 100644
--- a/table/metadata_builder_internal_test.go
+++ b/table/metadata_builder_internal_test.go
@@ -1083,7 +1083,7 @@ func TestRemoveSnapshotsPrunesSnapshotLogHistory(t
*testing.T) {
{SnapshotID: snapshot2ID, TimestampMs: baseTimestamp + 2},
{SnapshotID: snapshot3ID, TimestampMs: baseTimestamp + 3},
}
- builder.currentSnapshotID = ptr(snapshot3ID)
+ builder.currentSnapshotID = new(snapshot3ID)
builder.refs = map[string]SnapshotRef{
MainBranch: {SnapshotID: snapshot3ID, SnapshotRefType:
BranchRef},
}
@@ -1219,7 +1219,7 @@ func TestRemoveSnapshotsWithCurrentSnapshotAndEmptyLog(t
*testing.T) {
LastPartitionID: &lastPartitionID,
Props: iceberg.Properties{},
SnapshotList: []Snapshot{{SnapshotID: removedID},
{SnapshotID: currentID}},
- CurrentSnapshotID: ptr(currentID),
+ CurrentSnapshotID: new(currentID),
SnapshotLog: []SnapshotLogEntry{},
SortOrderList: []SortOrder{UnsortedSortOrder},
SnapshotRefs: map[string]SnapshotRef{
@@ -3796,8 +3796,8 @@ func fillNonZero(v reflect.Value, seen
map[reflect.Type]bool) bool {
return true
case reflect.Struct:
filled := false
- for i := range v.NumField() {
- if fillNonZero(fieldValue(v.Field(i)), seen) {
+ for _, field := range v.Fields() {
+ if fillNonZero(fieldValue(field), seen) {
filled = true
}
}
diff --git a/table/pos_delete_partitioned_fanout_writer_test.go
b/table/pos_delete_partitioned_fanout_writer_test.go
index 08d3aae2f..17229dd19 100644
--- a/table/pos_delete_partitioned_fanout_writer_test.go
+++ b/table/pos_delete_partitioned_fanout_writer_test.go
@@ -736,10 +736,6 @@ func (m *dataFileMatcher) Format(val iceberg.DataFile)
string {
// defaultPositionDeleteMatching is a convenience preset for the options we
want to match for position delete matching
var defaultPositionDeleteMatching =
[]dataFileMatcherOption{withContentTypeMatching(), withColumnSizesMatching(),
withCountMatching(), withFileFormatMatching(), withSpecIDMatching(),
withPartitionMatching(), withCountMatching(), withSortOrderIDMatching()}
-// ptr returns a pointer to v. A generic stand-in for the various one-off
-// ptr-helpers previously sprinkled across the internal package tests.
-func ptr[T any](v T) *T { return &v }
-
// Position deletes are ordered by (file_path, pos), never by a table sort
// order, so their sort order id stays null.
func TestPositionDeleteUnpartitionedSortOrderID(t *testing.T) {
diff --git a/table/rebuild_manifest_test.go b/table/rebuild_manifest_test.go
index b6df27e95..5a68ef99c 100644
--- a/table/rebuild_manifest_test.go
+++ b/table/rebuild_manifest_test.go
@@ -174,8 +174,8 @@ func TestStagedSnapshotStillValid(t *testing.T) {
{"v1 ignores sequence numbers", v1, &Snapshot{}, true},
{"v2 sequence number ahead", v2, &Snapshot{SequenceNumber:
v2.LastSequenceNumber() + 1}, true},
{"v2 sequence number equal", v2, &Snapshot{SequenceNumber:
v2.LastSequenceNumber()}, false},
- {"v3 first-row-id at the cursor", v3, &Snapshot{SequenceNumber:
v3.LastSequenceNumber() + 1, FirstRowID: ptr(v3.NextRowID())}, true},
- {"v3 first-row-id behind", v3, &Snapshot{SequenceNumber:
v3.LastSequenceNumber() + 1, FirstRowID: ptr(v3.NextRowID() - 1)}, false},
+ {"v3 first-row-id at the cursor", v3, &Snapshot{SequenceNumber:
v3.LastSequenceNumber() + 1, FirstRowID: new(v3.NextRowID())}, true},
+ {"v3 first-row-id behind", v3, &Snapshot{SequenceNumber:
v3.LastSequenceNumber() + 1, FirstRowID: new(v3.NextRowID() - 1)}, false},
{"v3 first-row-id missing", v3, &Snapshot{SequenceNumber:
v3.LastSequenceNumber() + 1}, false},
{"nil fresh metadata", nil, &Snapshot{}, true},
}
@@ -512,7 +512,7 @@ func TestRebuildFn_SummaryRebasedAgainstFreshParent(t
*testing.T) {
parentManifestListPath :=
"mem://default/table-location/metadata/fresh-parent-snap.avro"
out, createErr := wfs.Create(parentManifestListPath)
require.NoError(t, createErr)
- writeErr := iceberg.WriteManifestList(2, out, 77, nil, ptr(int64(0)),
0, nil)
+ writeErr := iceberg.WriteManifestList(2, out, 77, nil, new(int64(0)),
0, nil)
require.NoError(t, writeErr)
require.NoError(t, out.Close())
diff --git a/table/requirement_test.go b/table/requirement_test.go
index 0e580093c..19b41f7ac 100644
--- a/table/requirement_test.go
+++ b/table/requirement_test.go
@@ -228,7 +228,7 @@ func TestParseRequirementAcceptsExplicitZero(t *testing.T) {
{name: "default sort order id", data:
`{"type":"assert-default-sort-order-id","default-sort-order-id":0}`, expected:
table.AssertDefaultSortOrderID(0)},
{name: "last assigned field id", data:
`{"type":"assert-last-assigned-field-id","last-assigned-field-id":0}`,
expected: table.AssertLastAssignedFieldID(0)},
{name: "last assigned partition id", data:
`{"type":"assert-last-assigned-partition-id","last-assigned-partition-id":0}`,
expected: table.AssertLastAssignedPartitionID(0)},
- {name: "snapshot id", data:
`{"type":"assert-ref-snapshot-id","ref":"main","snapshot-id":0}`, expected:
table.AssertRefSnapshotID("main", ptr(int64(0)))},
+ {name: "snapshot id", data:
`{"type":"assert-ref-snapshot-id","ref":"main","snapshot-id":0}`, expected:
table.AssertRefSnapshotID("main", new(int64(0)))},
}
for _, tt := range tests {
@@ -261,7 +261,7 @@ func
TestParseRequirementRefRequiresRefButAllowsNullSnapshotID(t *testing.T) {
func TestParseRequirementRefAcceptsNumericSnapshotID(t *testing.T) {
actual, err :=
table.ParseRequirementBytes([]byte(`{"type":"assert-ref-snapshot-id","ref":"main","snapshot-id":42}`))
require.NoError(t, err)
- assert.Equal(t, table.AssertRefSnapshotID("main", ptr(int64(42))),
actual)
+ assert.Equal(t, table.AssertRefSnapshotID("main", new(int64(42))),
actual)
}
func TestAssertRefSnapshotIDValidate(t *testing.T) {
@@ -269,12 +269,12 @@ func TestAssertRefSnapshotIDValidate(t *testing.T) {
require.NoError(t, err)
t.Run("matching ref passes", func(t *testing.T) {
- req := table.AssertRefSnapshotID("test",
ptr(int64(3051729675574597004)))
+ req := table.AssertRefSnapshotID("test",
new(int64(3051729675574597004)))
assert.NoError(t, req.Validate(meta))
})
t.Run("mismatched snapshot id includes expected and found", func(t
*testing.T) {
- req := table.AssertRefSnapshotID("test", ptr(int64(1)))
+ req := table.AssertRefSnapshotID("test", new(int64(1)))
err := req.Validate(meta)
require.Error(t, err)
assert.Contains(t, err.Error(), `"test"`)
@@ -292,7 +292,7 @@ func TestAssertRefSnapshotIDValidate(t *testing.T) {
})
t.Run("ref missing but expected includes expected snapshot", func(t
*testing.T) {
- req := table.AssertRefSnapshotID("nonexistent", ptr(int64(42)))
+ req := table.AssertRefSnapshotID("nonexistent", new(int64(42)))
err := req.Validate(meta)
require.Error(t, err)
assert.Contains(t, err.Error(), `"nonexistent"`)
@@ -301,7 +301,7 @@ func TestAssertRefSnapshotIDValidate(t *testing.T) {
})
t.Run("nil metadata returns error", func(t *testing.T) {
- req := table.AssertRefSnapshotID("main", ptr(int64(1)))
+ req := table.AssertRefSnapshotID("main", new(int64(1)))
assert.Error(t, req.Validate(nil))
})
diff --git a/table/scan_metrics_test.go b/table/scan_metrics_test.go
index 9a566fee7..0ed2f6118 100644
--- a/table/scan_metrics_test.go
+++ b/table/scan_metrics_test.go
@@ -174,8 +174,8 @@ func TestApplyResultDeleteMetrics(t *testing.T) {
// the whole Puffin file size, so filesize (the Puffin length) must be
ignored.
dv := &dvMockDataFile{
mockDataFile: mockDataFile{path: "s3://b/deletes.puffin",
filesize: 9999},
- referencedDataFile: strPtr("s3://b/data-2.parquet"),
- contentSizeInBytes: int64Ptr(10),
+ referencedDataFile: new("s3://b/data-2.parquet"),
+ contentSizeInBytes: new(int64(10)),
}
// posA applies to both data-file tasks: matching Java's per-task
@@ -216,12 +216,12 @@ func TestApplyResultDeleteMetricsDVsShareOnePuffin(t
*testing.T) {
dv1 := &dvMockDataFile{
mockDataFile: mockDataFile{path: puffin, filesize: 9999},
referencedDataFile: &ref1,
- contentSizeInBytes: int64Ptr(30),
+ contentSizeInBytes: new(int64(30)),
}
dv2 := &dvMockDataFile{
mockDataFile: mockDataFile{path: puffin, filesize: 9999},
referencedDataFile: &ref2,
- contentSizeInBytes: int64Ptr(70),
+ contentSizeInBytes: new(int64(70)),
}
tasks := []FileScanTask{
@@ -303,7 +303,7 @@ func TestPlanFilesEmitsReportForRealSnapshot(t *testing.T) {
df := newTestDataFile(t, spec,
"mem://default/table-location/data-1.parquet", nil)
entries := []iceberg.ManifestEntry{
- iceberg.NewManifestEntry(iceberg.EntryStatusADDED,
int64Ptr(snapshotID), nil, nil, df),
+ iceberg.NewManifestEntry(iceberg.EntryStatusADDED,
new(snapshotID), nil, nil, df),
}
var manifestBuf bytes.Buffer
manifest, err := iceberg.WriteManifest(manifestPath, &manifestBuf, 2,
spec, schema, snapshotID, entries)
diff --git a/table/scan_planning.go b/table/scan_planning.go
index c41fca5ad..4b6a12162 100644
--- a/table/scan_planning.go
+++ b/table/scan_planning.go
@@ -76,7 +76,7 @@ type ScanPlanningMetadata interface {
// Compile-time guard that the full Metadata interface still satisfies the
// narrowed planner view, so callers can pass a table.Metadata directly.
-var _ ScanPlanningMetadata = (Metadata)(nil)
+var _ ScanPlanningMetadata = Metadata(nil)
// Compile-time guard that Scan exposes the lifecycle contract as io.Closer.
var _ io.Closer = (*Scan)(nil)
diff --git a/table/scanner_empty_manifest_bench_test.go
b/table/scanner_empty_manifest_bench_test.go
index 1d21f6f5f..af4634343 100644
--- a/table/scanner_empty_manifest_bench_test.go
+++ b/table/scanner_empty_manifest_bench_test.go
@@ -105,7 +105,7 @@ func newEmptyManifestBenchmarkTable(
manifestListPath := tableLocation + "/metadata/snap-1.avro"
var listBuf bytes.Buffer
- require.NoError(b, iceberg.WriteManifestList(2, &listBuf, snapshotID,
nil, ptr(sequenceNum), 0, manifests))
+ require.NoError(b, iceberg.WriteManifestList(2, &listBuf, snapshotID,
nil, new(sequenceNum), 0, manifests))
require.NoError(b, fs.WriteFile(manifestListPath, listBuf.Bytes()))
meta, err := NewMetadata(schema, &spec, UnsortedSortOrder,
tableLocation, nil)
diff --git a/table/scanner_manifest_entries_bench_test.go
b/table/scanner_manifest_entries_bench_test.go
index 71caf1493..58651f6d3 100644
--- a/table/scanner_manifest_entries_bench_test.go
+++ b/table/scanner_manifest_entries_bench_test.go
@@ -146,9 +146,9 @@ func benchmarkManifestEntries(count int, content
iceberg.ManifestContent) []iceb
&mockDataFile{path: "eq-delete.parquet", contentType:
iceberg.EntryContentEqDeletes},
&dvMockDataFile{
mockDataFile: mockDataFile{path:
"dv.puffin", contentType: iceberg.EntryContentPosDeletes, format:
iceberg.PuffinFile},
- referencedDataFile: strPtr("data.parquet"),
- contentOffset: int64Ptr(0),
- contentSizeInBytes: int64Ptr(128),
+ referencedDataFile: new("data.parquet"),
+ contentOffset: new(int64(0)),
+ contentSizeInBytes: new(int64(128)),
},
}
}
diff --git a/table/snapshot_producers.go b/table/snapshot_producers.go
index 490fb2528..9cb0b1dd9 100644
--- a/table/snapshot_producers.go
+++ b/table/snapshot_producers.go
@@ -1762,16 +1762,16 @@ func (sp *snapshotProducer)
commitManifests(newManifests, addedContent []iceberg
// creates it).
baseHeadID := sp.txn.baseRefSnapshotID(branch)
- return []Update{
- addSnap,
- // Carry over the branch's existing retention settings
so advancing
- // the ref on commit does not silently discard them.
The update
- // encodes exactly the current ref's retention
(settings the branch
- // lacks stay 0 and are dropped by the `omitempty`
tags); the catalog
- // applies a set-snapshot-ref as a pure replace, so
this fully
- // determines the resulting ref rather than merging
with the old one.
- sp.txn.meta.NewRetainingSnapshotRefUpdate(branch,
sp.snapshotID, BranchRef),
- }, []Requirement{
- AssertRefSnapshotID(branch, baseHeadID),
- }, nil
+ updates := []Update{
+ addSnap,
+ // Carry over the branch's existing retention settings so
advancing
+ // the ref on commit does not silently discard them. The update
+ // encodes exactly the current ref's retention (settings the
branch
+ // lacks stay 0 and are dropped by the `omitempty` tags); the
catalog
+ // applies a set-snapshot-ref as a pure replace, so this fully
+ // determines the resulting ref rather than merging with the
old one.
+ sp.txn.meta.NewRetainingSnapshotRefUpdate(branch,
sp.snapshotID, BranchRef),
+ }
+
+ return updates, []Requirement{AssertRefSnapshotID(branch, baseHeadID)},
nil
}
diff --git a/table/snapshot_producers_test.go b/table/snapshot_producers_test.go
index 47e60e13d..f69bdd1a9 100644
--- a/table/snapshot_producers_test.go
+++ b/table/snapshot_producers_test.go
@@ -976,7 +976,7 @@ func TestRebuildManifestListSummaryFailureCreatesNoOutput(t
*testing.T) {
parentManifestList :=
"mem://default/table-location/metadata/fresh-parent.avro"
out, err := wfs.Create(parentManifestList)
require.NoError(t, err)
- require.NoError(t, iceberg.WriteManifestList(2, out, 77, nil,
ptr(int64(0)), 0, nil))
+ require.NoError(t, iceberg.WriteManifestList(2, out, 77, nil,
new(int64(0)), 0, nil))
require.NoError(t, out.Close())
sp.op = Operation("unsupported")
@@ -1924,7 +1924,7 @@ func TestSummaryOnRetry_SkipsAlreadyRemovedDeleteFile(t
*testing.T) {
parentManifestList :=
"mem://default/table-location/metadata/fresh-parent-skip.avro"
out, err := wfs.Create(parentManifestList)
require.NoError(t, err)
- require.NoError(t, iceberg.WriteManifestList(2, out, 77, nil,
ptr(int64(0)), 0, nil))
+ require.NoError(t, iceberg.WriteManifestList(2, out, 77, nil,
new(int64(0)), 0, nil))
require.NoError(t, out.Close())
freshParent := &Snapshot{
@@ -2027,7 +2027,7 @@ func
TestCheckRemovedFiles_AbortsWhenRewriteTargetMissing(t *testing.T) {
parentManifestList :=
"mem://default/table-location/metadata/fresh-parent-diverged.avro"
out, err := wfs.Create(parentManifestList)
require.NoError(t, err)
- require.NoError(t, iceberg.WriteManifestList(2, out, 99, nil,
ptr(int64(0)), 0, nil))
+ require.NoError(t, iceberg.WriteManifestList(2, out, 99, nil,
new(int64(0)), 0, nil))
require.NoError(t, out.Close())
freshParent := &Snapshot{SnapshotID: 99, ManifestList:
parentManifestList}
diff --git a/table/snapshots_test.go b/table/snapshots_test.go
index b6b5f2311..e81b6c7e6 100644
--- a/table/snapshots_test.go
+++ b/table/snapshots_test.go
@@ -370,32 +370,32 @@ func TestValidateRowLineage(t *testing.T) {
},
{
name: "valid: both set",
- firstRowID: ptr(int64(0)),
- addedRows: ptr(int64(100)),
+ firstRowID: new(int64(0)),
+ addedRows: new(int64(100)),
wantErr: "",
},
{
name: "valid: zero added rows",
- firstRowID: ptr(int64(30)),
- addedRows: ptr(int64(0)),
+ firstRowID: new(int64(30)),
+ addedRows: new(int64(0)),
wantErr: "",
},
{
name: "invalid: first-row-id set but added-rows
nil",
- firstRowID: ptr(int64(0)),
+ firstRowID: new(int64(0)),
addedRows: nil,
wantErr: "added-rows is required when first-row-id
is set",
},
{
name: "invalid: negative added-rows",
- firstRowID: ptr(int64(0)),
- addedRows: ptr(int64(-1)),
+ firstRowID: new(int64(0)),
+ addedRows: new(int64(-1)),
wantErr: "added-rows cannot be negative: -1",
},
{
name: "invalid: negative first-row-id",
- firstRowID: ptr(int64(-1)),
- addedRows: ptr(int64(100)),
+ firstRowID: new(int64(-1)),
+ addedRows: new(int64(100)),
wantErr: "first-row-id cannot be negative: -1",
},
}
@@ -419,10 +419,6 @@ func TestValidateRowLineage(t *testing.T) {
}
}
-func ptr[T any](v T) *T {
- return &v
-}
-
func TestSnapshotUnmarshalRequiresSnapshotIDAndTimestamp(t *testing.T) {
tests := []struct {
name string
diff --git a/table/sorting.go b/table/sorting.go
index 9b80b9f03..80c288740 100644
--- a/table/sorting.go
+++ b/table/sorting.go
@@ -245,8 +245,7 @@ func validateSortSourceID(id int, binding orderBinding)
error {
func unmarshalJSONField(data json.RawMessage, field string, value any) error {
if err := json.Unmarshal(data, value); err != nil {
- var typeErr *json.UnmarshalTypeError
- if errors.As(err, &typeErr) {
+ if typeErr, ok := errors.AsType[*json.UnmarshalTypeError](err);
ok {
typeErr.Struct = ""
typeErr.Field = field
}
diff --git a/table/substrait/substrait.go b/table/substrait/substrait.go
index bc8b36655..e09fc4629 100644
--- a/table/substrait/substrait.go
+++ b/table/substrait/substrait.go
@@ -136,7 +136,8 @@ func (c convertToSubstrait) Map(m iceberg.MapType,
keyResult, valResult types.Ty
}
func (convertToSubstrait) Primitive(iceberg.PrimitiveType) types.Type {
panic("should not be called") }
-func (convertToSubstrait) Variant(iceberg.VariantType) types.Type {
panic("should not be called") }
+
+func (convertToSubstrait) Variant(iceberg.VariantType) types.Type {
panic("should not be called") }
func (convertToSubstrait) VisitFixed(f iceberg.FixedType) types.Type {
return &types.FixedBinaryType{Length: int32(f.Len())}
diff --git a/table/transaction_internal_test.go
b/table/transaction_internal_test.go
index ce2d4c2b0..b9eedc2db 100644
--- a/table/transaction_internal_test.go
+++ b/table/transaction_internal_test.go
@@ -724,7 +724,7 @@ func TestExpireSnapshotsRetainsYoungUnreferencedSnapshots(t
*testing.T) {
now := time.Now().UnixMilli()
require.NoError(t, txn.meta.AddSnapshot(&Snapshot{
SnapshotID: 30,
- ParentSnapshotID: transactionTestPtr(int64(10)),
+ ParentSnapshotID: new(int64(10)),
SequenceNumber: 3,
ManifestList:
"mem://default/table-location/metadata/manifest-30.avro",
Summary: &Summary{Operation: OpAppend},
@@ -802,7 +802,7 @@ func
TestExpireSnapshotsRetainsOnlyRefHeadsWhenMinSnapshotsToKeepIsZero(t *testi
// interior ancestor held by no ref head.
require.NoError(t, txn.meta.AddSnapshot(&Snapshot{
SnapshotID: 30,
- ParentSnapshotID: transactionTestPtr(int64(20)),
+ ParentSnapshotID: new(int64(20)),
SequenceNumber: 3,
ManifestList:
"mem://default/table-location/metadata/manifest-30.avro",
Summary: &Summary{Operation: OpAppend},
@@ -832,7 +832,7 @@ func
TestExpireSnapshotsRetainsOnlyRefHeadsWhenMinSnapshotsToKeepIsZero(t *testi
// the retention walk, leaving AncestorsOf's cycle guard as the only exit.
func TestExpireSnapshotsTerminatesOnParentCycle(t *testing.T) {
txn := newTransactionWithSnapshotRefs(t)
- expireSnapshotsSnapshot(t, txn, 10).ParentSnapshotID =
transactionTestPtr(int64(20))
+ expireSnapshotsSnapshot(t, txn, 10).ParentSnapshotID = new(int64(20))
done := make(chan error, 1)
go func() { done <- txn.ExpireSnapshots() }()
@@ -1480,12 +1480,12 @@ func
TestTransactionApplyKeepsRefAssertionsForDistinctRefs(t *testing.T) {
base := int64(10)
err := txn.apply(nil, []Requirement{
AssertRefSnapshotID(MainBranch, &base),
- AssertRefSnapshotID("feature", transactionTestPtr(int64(20))),
+ AssertRefSnapshotID("feature", new(int64(20))),
})
require.NoError(t, err)
require.Len(t, txn.reqs, 2)
requireContainsRefSnapshotRequirement(t, txn.reqs, MainBranch, &base)
- requireContainsRefSnapshotRequirement(t, txn.reqs, "feature",
transactionTestPtr(int64(20)))
+ requireContainsRefSnapshotRequirement(t, txn.reqs, "feature",
new(int64(20)))
}
// TestTransactionApplyDedupesIdenticalNonRefRequirements confirms that non-ref
@@ -1541,7 +1541,7 @@ func TestRollbackToSnapshotPreservesRetention(t
*testing.T) {
require.NoError(t, txn.meta.AddSnapshot(&Snapshot{
SnapshotID: 20,
- ParentSnapshotID: transactionTestPtr(int64(10)),
+ ParentSnapshotID: new(int64(10)),
SequenceNumber: 2,
ManifestList:
"mem://default/table-location/metadata/manifest-20.avro",
Summary: &Summary{Operation: OpAppend},
@@ -1582,7 +1582,7 @@ func newTransactionWithSnapshotRefs(t *testing.T)
*Transaction {
require.NoError(t, txn.meta.AddSnapshot(&Snapshot{
SnapshotID: 20,
- ParentSnapshotID: transactionTestPtr(int64(10)),
+ ParentSnapshotID: new(int64(10)),
SequenceNumber: 2,
ManifestList:
"mem://default/table-location/metadata/manifest-20.avro",
Summary: &Summary{Operation: OpAppend},
@@ -1608,10 +1608,6 @@ func requireContainsRefSnapshotRequirement(t *testing.T,
requirements []Requirem
t.Fatalf("expected assertRefSnapshotID requirement for ref %q and
snapshot id %v not found", ref, snapshotID)
}
-func transactionTestPtr[T any](v T) *T {
- return &v
-}
-
func transactionTestInt64PtrEqual(left, right *int64) bool {
if left == nil || right == nil {
return left == right
@@ -1644,7 +1640,7 @@ func newRollbackBranchTable(t *testing.T) *Table {
}))
require.NoError(t, txn.meta.AddSnapshot(&Snapshot{
SnapshotID: 20,
- ParentSnapshotID: transactionTestPtr(int64(10)),
+ ParentSnapshotID: new(int64(10)),
SequenceNumber: 2,
ManifestList:
"mem://default/table-location/metadata/manifest-20.avro",
Summary: &Summary{Operation: OpAppend},
@@ -1652,7 +1648,7 @@ func newRollbackBranchTable(t *testing.T) *Table {
}))
require.NoError(t, txn.meta.AddSnapshot(&Snapshot{
SnapshotID: 30,
- ParentSnapshotID: transactionTestPtr(int64(20)),
+ ParentSnapshotID: new(int64(20)),
SequenceNumber: 3,
ManifestList:
"mem://default/table-location/metadata/manifest-30.avro",
Summary: &Summary{Operation: OpAppend},
@@ -1660,7 +1656,7 @@ func newRollbackBranchTable(t *testing.T) *Table {
}))
require.NoError(t, txn.meta.AddSnapshot(&Snapshot{
SnapshotID: 40,
- ParentSnapshotID: transactionTestPtr(int64(10)),
+ ParentSnapshotID: new(int64(10)),
SequenceNumber: 4,
ManifestList:
"mem://default/table-location/metadata/manifest-40.avro",
Summary: &Summary{Operation: OpAppend},
@@ -1725,7 +1721,7 @@ func TestRollbackToSnapshotOnBranchDoesNotCorruptMain(t
*testing.T) {
require.Equal(t, BranchRef, featureRef.SnapshotRefType, "the
rolled-back ref must stay a branch")
requireUntouchedRollbackRefs(t, branchTxn, "feature")
- requireContainsRefSnapshotRequirement(t, branchTxn.reqs, "feature",
transactionTestPtr(int64(30)))
+ requireContainsRefSnapshotRequirement(t, branchTxn.reqs, "feature",
new(int64(30)))
}
// TestRollbackToSnapshotValidatesAncestryAgainstTargetBranch rejects snapshot
20:
@@ -1822,7 +1818,7 @@ func TestRollbackToSnapshotOnMainIsUnchanged(t
*testing.T) {
require.Equal(t, int64(10), *txn.meta.currentSnapshotID,
"rolling main back must also move the current-snapshot
pointer")
requireUntouchedRollbackRefs(t, txn, MainBranch)
- requireContainsRefSnapshotRequirement(t, txn.reqs, MainBranch,
transactionTestPtr(int64(20)))
+ requireContainsRefSnapshotRequirement(t, txn.reqs, MainBranch,
new(int64(20)))
})
t.Run("refuses when only a branch has a head", func(t *testing.T) {
@@ -1848,7 +1844,7 @@ func TestRollbackToSnapshotOnMainIsUnchanged(t
*testing.T) {
func TestRollbackToSnapshotSharesOneBaseAssertionWithProducer(t *testing.T) {
producerAssertion := func(txn *Transaction) error {
return txn.apply(nil, []Requirement{
- AssertRefSnapshotID("feature",
transactionTestPtr(int64(30))),
+ AssertRefSnapshotID("feature", new(int64(30))),
})
}
diff --git a/website/src/install.md b/website/src/install.md
index eb02d6d59..44985fbfb 100644
--- a/website/src/install.md
+++ b/website/src/install.md
@@ -24,7 +24,7 @@ In this quickstart, we’ll glean insights from code segments
and learn how to:
## Requirements
<div class="warning">
-Go 1.25 or later is required to build.
+Go 1.26 or later is required to build.
</div>
## Installation