This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git
The following commit(s) were added to refs/heads/main by this push:
new 25ca50563 refactor(table)!: make SnapshotAsOf inclusive before v1
(#2322)
25ca50563 is described below
commit 25ca50563000e6e7732ce51342278ee0bfe37cb2
Author: Minh Vu <[email protected]>
AuthorDate: Mon Oct 26 19:28:04 2026 +0100
refactor(table)!: make SnapshotAsOf inclusive before v1 (#2322)
* refactor(table)!: make SnapshotAsOf inclusive before v1
Signed-off-by: Minh Vu <[email protected]>
* chore: sync release notes with main to resolve conflicts
---------
Signed-off-by: Minh Vu <[email protected]>
Co-authored-by: Matt Topol <[email protected]>
---
cmd/iceberg/upgrade_rollback.go | 2 +-
table/table.go | 8 ++++---
table/time_travel_test.go | 46 ++++++++++-------------------------------
3 files changed, 17 insertions(+), 39 deletions(-)
diff --git a/cmd/iceberg/upgrade_rollback.go b/cmd/iceberg/upgrade_rollback.go
index 099997665..1d89abcc3 100644
--- a/cmd/iceberg/upgrade_rollback.go
+++ b/cmd/iceberg/upgrade_rollback.go
@@ -169,7 +169,7 @@ func resolveRollbackSnapshotID(tbl *table.Table, cmd
*RollbackCmd) (int64, error
return 0, err
}
- if snap := tbl.SnapshotAsOf(timestamp.UnixMilli(), true); snap != nil {
+ if snap := tbl.SnapshotAsOf(timestamp.UnixMilli()); snap != nil {
return snap.SnapshotID, nil
}
diff --git a/table/table.go b/table/table.go
index b266a0165..5ffb5eabe 100644
--- a/table/table.go
+++ b/table/table.go
@@ -1178,9 +1178,11 @@ func backoffDuration(attempt uint, minMs, maxMs uint64)
time.Duration {
return time.Duration(wait) * time.Millisecond
}
-// SnapshotAsOf finds the snapshot that was current as of or right before the
given timestamp.
-func (t Table) SnapshotAsOf(timestampMs int64, inclusive bool) *Snapshot {
- entry, ok := SnapshotLogEntryAsOf(t.metadata.SnapshotLogs(),
timestampMs, inclusive)
+// SnapshotAsOf returns the snapshot that was current at or before timestampMs,
+// measured in milliseconds since the Unix epoch. It returns nil when no
+// snapshot was current at or before that time.
+func (t Table) SnapshotAsOf(timestampMs int64) *Snapshot {
+ entry, ok := SnapshotLogEntryAsOf(t.metadata.SnapshotLogs(),
timestampMs, true)
if ok {
return t.metadata.SnapshotByID(entry.SnapshotID)
}
diff --git a/table/time_travel_test.go b/table/time_travel_test.go
index b047f1f43..15ba8a5de 100644
--- a/table/time_travel_test.go
+++ b/table/time_travel_test.go
@@ -75,25 +75,18 @@ func TestSnapshotAsOf(t *testing.T) {
metadata: meta,
}
- t.Run("SnapshotAsOf finds exact timestamp match (inclusive)", func(t
*testing.T) {
+ t.Run("SnapshotAsOf includes an exact timestamp match", func(t
*testing.T) {
timestamp := baseTime.Add(2 * time.Hour).UnixMilli()
- snapshot := table.SnapshotAsOf(timestamp, true)
+ snapshot := table.SnapshotAsOf(timestamp)
require.NotNil(t, snapshot)
assert.Equal(t, int64(2000), snapshot.SnapshotID)
assert.Equal(t, timestamp, snapshot.TimestampMs)
})
- t.Run("SnapshotAsOf finds exact timestamp match (exclusive)", func(t
*testing.T) {
- timestamp := baseTime.Add(2 * time.Hour).UnixMilli()
- snapshot := table.SnapshotAsOf(timestamp, false)
- require.NotNil(t, snapshot)
- assert.Equal(t, int64(1000), snapshot.SnapshotID) // Should get
previous snapshot
- })
-
t.Run("SnapshotAsOf finds snapshot before timestamp", func(t
*testing.T) {
// Query 90 minutes ago (between snapshots 2 and 3)
timestamp := baseTime.Add(150 * time.Minute).UnixMilli()
- snapshot := table.SnapshotAsOf(timestamp, true)
+ snapshot := table.SnapshotAsOf(timestamp)
require.NotNil(t, snapshot)
assert.Equal(t, int64(2000), snapshot.SnapshotID) // Should get
snapshot 2
})
@@ -101,7 +94,7 @@ func TestSnapshotAsOf(t *testing.T) {
t.Run("SnapshotAsOf finds most recent snapshot for future timestamp",
func(t *testing.T) {
// Query future timestamp
timestamp := baseTime.Add(4 * time.Hour).UnixMilli()
- snapshot := table.SnapshotAsOf(timestamp, true)
+ snapshot := table.SnapshotAsOf(timestamp)
require.NotNil(t, snapshot)
assert.Equal(t, int64(3000), snapshot.SnapshotID) // Should get
most recent
})
@@ -109,22 +102,9 @@ func TestSnapshotAsOf(t *testing.T) {
t.Run("SnapshotAsOf returns nil for timestamp before first snapshot",
func(t *testing.T) {
// Query before first snapshot
timestamp := baseTime.Add(-1 * time.Hour).UnixMilli()
- snapshot := table.SnapshotAsOf(timestamp, true)
- assert.Nil(t, snapshot)
- })
-
- t.Run("SnapshotAsOf returns nil for timestamp equal to first snapshot
(exclusive)", func(t *testing.T) {
- timestamp := baseTime.UnixMilli()
- snapshot := table.SnapshotAsOf(timestamp, false)
+ snapshot := table.SnapshotAsOf(timestamp)
assert.Nil(t, snapshot)
})
-
- t.Run("SnapshotAsOf with inclusive=true (default behavior)", func(t
*testing.T) {
- timestamp := baseTime.Add(2 * time.Hour).UnixMilli()
- snapshot := table.SnapshotAsOf(timestamp, true)
- require.NotNil(t, snapshot)
- assert.Equal(t, int64(2000), snapshot.SnapshotID)
- })
}
func TestSnapshotAsOfWithOutOfOrderSnapshotLog(t *testing.T) {
@@ -149,7 +129,7 @@ func TestSnapshotAsOfWithOutOfOrderSnapshotLog(t
*testing.T) {
}
queryTime := baseTime + 2500
- snapshot := tbl.SnapshotAsOf(queryTime, true)
+ snapshot := tbl.SnapshotAsOf(queryTime)
require.NotNil(t, snapshot)
assert.Equal(t, int64(1000), snapshot.SnapshotID)
@@ -158,10 +138,6 @@ func TestSnapshotAsOfWithOutOfOrderSnapshotLog(t
*testing.T) {
require.NoError(t, err)
require.NotNil(t, snapshot)
assert.Equal(t, int64(1000), snapshot.SnapshotID)
-
- snapshot = tbl.SnapshotAsOf(baseTime+2000, false)
- require.NotNil(t, snapshot)
- assert.Equal(t, int64(2000), snapshot.SnapshotID)
}
func TestSnapshotAsOfWithEqualTimestampsUsesFirstLogEntry(t *testing.T) {
@@ -179,7 +155,7 @@ func TestSnapshotAsOfWithEqualTimestampsUsesFirstLogEntry(t
*testing.T) {
require.NoError(t, err)
tbl := Table{metadata: meta}
- snapshot := tbl.SnapshotAsOf(baseTime+1000, true)
+ snapshot := tbl.SnapshotAsOf(baseTime + 1000)
require.NotNil(t, snapshot)
assert.Equal(t, int64(1000), snapshot.SnapshotID)
@@ -478,7 +454,7 @@ func TestSnapshotAsOfEdgeCases(t *testing.T) {
metadata: meta,
}
- snapshot := table.SnapshotAsOf(time.Now().UnixMilli(), true)
+ snapshot := table.SnapshotAsOf(time.Now().UnixMilli())
assert.Nil(t, snapshot)
scan := table.Scan(WithSnapshotAsOf(time.Now().UnixMilli()))
@@ -513,16 +489,16 @@ func TestSnapshotAsOfEdgeCases(t *testing.T) {
}
// Before snapshot
- snapshot :=
table.SnapshotAsOf(now.Add(-1*time.Hour).UnixMilli(), true)
+ snapshot := table.SnapshotAsOf(now.Add(-1 *
time.Hour).UnixMilli())
assert.Nil(t, snapshot)
// At snapshot timestamp
- snapshot = table.SnapshotAsOf(now.UnixMilli(), true)
+ snapshot = table.SnapshotAsOf(now.UnixMilli())
require.NotNil(t, snapshot)
assert.Equal(t, int64(1000), snapshot.SnapshotID)
// After snapshot
- snapshot = table.SnapshotAsOf(now.Add(1*time.Hour).UnixMilli(),
true)
+ snapshot = table.SnapshotAsOf(now.Add(1 *
time.Hour).UnixMilli())
require.NotNil(t, snapshot)
assert.Equal(t, int64(1000), snapshot.SnapshotID)
})