diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java index 70665ca138653..949f7c7fe1257 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java @@ -17,6 +17,8 @@ import com.facebook.airlift.log.Logger; import com.facebook.presto.common.RuntimeStats; import com.facebook.presto.common.Subfield; +import com.facebook.presto.common.predicate.Domain; +import com.facebook.presto.common.predicate.Range; import com.facebook.presto.common.predicate.TupleDomain; import com.facebook.presto.common.type.BigintType; import com.facebook.presto.common.type.SqlTimestampWithTimeZone; @@ -139,12 +141,15 @@ import static com.facebook.presto.iceberg.IcebergColumnHandle.IS_DELETED_COLUMN_METADATA; import static com.facebook.presto.iceberg.IcebergColumnHandle.PATH_COLUMN_HANDLE; import static com.facebook.presto.iceberg.IcebergColumnHandle.PATH_COLUMN_METADATA; +import static com.facebook.presto.iceberg.IcebergColumnHandle.SNAPSHOT_ID_COLUMN_HANDLE; +import static com.facebook.presto.iceberg.IcebergColumnHandle.SNAPSHOT_ID_COLUMN_METADATA; import static com.facebook.presto.iceberg.IcebergErrorCode.ICEBERG_COMMIT_ERROR; import static com.facebook.presto.iceberg.IcebergErrorCode.ICEBERG_INVALID_SNAPSHOT_ID; import static com.facebook.presto.iceberg.IcebergMetadataColumn.DATA_SEQUENCE_NUMBER; import static com.facebook.presto.iceberg.IcebergMetadataColumn.DELETE_FILE_PATH; import static com.facebook.presto.iceberg.IcebergMetadataColumn.FILE_PATH; import static com.facebook.presto.iceberg.IcebergMetadataColumn.IS_DELETED; +import static com.facebook.presto.iceberg.IcebergMetadataColumn.SNAPSHOT_ID; import static com.facebook.presto.iceberg.IcebergMetadataColumn.UPDATE_ROW_DATA; import static com.facebook.presto.iceberg.IcebergPartitionType.ALL; import static com.facebook.presto.iceberg.IcebergSessionProperties.getCompressionCodec; @@ -282,6 +287,42 @@ public ConnectorTableLayoutResult getTableLayoutForConstraint( IcebergTableHandle handle = (IcebergTableHandle) table; Table icebergTable = getIcebergTable(session, handle.getSchemaTableName()); + IcebergTableName name = IcebergTableName.from(handle.getTableName()); + + Map domains = constraint.getSummary().getDomains().orElse(Collections.emptyMap()); + for (Map.Entry entry : domains.entrySet()) { + IcebergColumnHandle column = (IcebergColumnHandle) entry.getKey(); + + if (column.getName().equalsIgnoreCase("$snapshot_id")) { + Domain domain = entry.getValue(); + + if (domain.isSingleValue()) { + Optional snapshotId = Optional.of(((Number) domain.getSingleValue()).longValue()); + handle = handle.withUpdatedIcebergTableName( + new IcebergTableName(name.getTableName(), name.getTableType(), snapshotId, name.getChangelogEndSnapshot())); + } + else if (domain.getValues().getRanges().getOrderedRanges().size() == 1) { + Range range = domain.getValues().getRanges().getOrderedRanges().get(0); + if (range.isSingleValue()) { + Optional snapshotId = Optional.of(((Number) range.getSingleValue()).longValue()); + handle = handle.withUpdatedIcebergTableName( + new IcebergTableName(name.getTableName(), name.getTableType(), snapshotId, name.getChangelogEndSnapshot())); + } + else if (!range.isLowUnbounded() && range.isLowInclusive() && range.isHighUnbounded()) { + // Only support >= X + Optional lower = Optional.of(((Number) range.getLowBoundedValue()).longValue()); + handle = handle.withUpdatedIcebergTableName( + new IcebergTableName(name.getTableName(), name.getTableType(), lower, name.getChangelogEndSnapshot())); + } + else { + throw new PrestoException(NOT_SUPPORTED, "Unsupported predicate for $snapshot_id; only >= constant is allowed"); + } + } + else { + throw new PrestoException(NOT_SUPPORTED, "Unsupported complex predicate for $snapshot_id; only >= constant is allowed"); + } + } + } List partitionColumns = getPartitionKeyColumnHandles(handle, icebergTable, typeManager); TupleDomain partitionColumnPredicate = TupleDomain.withColumnDomains(Maps.filterKeys(constraint.getSummary().getDomains().get(), Predicates.in(partitionColumns))); @@ -444,6 +485,7 @@ protected ConnectorTableMetadata getTableOrViewMetadata(ConnectorSession session columns.add(DATA_SEQUENCE_NUMBER_COLUMN_METADATA); columns.add(IS_DELETED_COLUMN_METADATA); columns.add(DELETE_FILE_PATH_COLUMN_METADATA); + columns.add(SNAPSHOT_ID_COLUMN_METADATA); } return new ConnectorTableMetadata(table, columns.build(), createMetadataProperties(icebergTable, session), getTableComment(icebergTable)); } @@ -955,6 +997,7 @@ public Map getColumnHandles(ConnectorSession session, Conn columnHandles.put(DATA_SEQUENCE_NUMBER.getColumnName(), DATA_SEQUENCE_NUMBER_COLUMN_HANDLE); columnHandles.put(IS_DELETED.getColumnName(), IS_DELETED_COLUMN_HANDLE); columnHandles.put(DELETE_FILE_PATH.getColumnName(), DELETE_FILE_PATH_COLUMN_HANDLE); + columnHandles.put(SNAPSHOT_ID.getColumnName(), SNAPSHOT_ID_COLUMN_HANDLE); } return columnHandles.build(); } diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergColumnHandle.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergColumnHandle.java index 62fafea0d48d8..2c83c0b79960b 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergColumnHandle.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergColumnHandle.java @@ -37,6 +37,7 @@ import static com.facebook.presto.iceberg.IcebergMetadataColumn.DELETE_FILE_PATH; import static com.facebook.presto.iceberg.IcebergMetadataColumn.FILE_PATH; import static com.facebook.presto.iceberg.IcebergMetadataColumn.IS_DELETED; +import static com.facebook.presto.iceberg.IcebergMetadataColumn.SNAPSHOT_ID; import static com.facebook.presto.iceberg.IcebergMetadataColumn.UPDATE_ROW_DATA; import static com.facebook.presto.iceberg.TypeConverter.toPrestoType; import static com.google.common.base.Preconditions.checkArgument; @@ -56,6 +57,8 @@ public class IcebergColumnHandle public static final ColumnMetadata IS_DELETED_COLUMN_METADATA = getColumnMetadata(IS_DELETED); public static final IcebergColumnHandle DELETE_FILE_PATH_COLUMN_HANDLE = getIcebergColumnHandle(DELETE_FILE_PATH); public static final ColumnMetadata DELETE_FILE_PATH_COLUMN_METADATA = getColumnMetadata(DELETE_FILE_PATH); + public static final IcebergColumnHandle SNAPSHOT_ID_COLUMN_HANDLE = getIcebergColumnHandle(SNAPSHOT_ID); + public static final ColumnMetadata SNAPSHOT_ID_COLUMN_METADATA = getColumnMetadata(SNAPSHOT_ID); private final ColumnIdentity columnIdentity; private final Type type; @@ -186,6 +189,11 @@ public boolean isDataSequenceNumberColumn() return getColumnIdentity().getId() == DATA_SEQUENCE_NUMBER.getId(); } + public boolean isSnapshotId() + { + return getColumnIdentity().getId() == SNAPSHOT_ID.getId(); + } + public boolean isDeletedColumn() { return getColumnIdentity().getId() == IS_DELETED.getId(); diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergMetadataColumn.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergMetadataColumn.java index 5862fba4975f8..d851c80a025f4 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergMetadataColumn.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergMetadataColumn.java @@ -33,6 +33,7 @@ public enum IcebergMetadataColumn { FILE_PATH(MetadataColumns.FILE_PATH.fieldId(), "$path", VARCHAR, PRIMITIVE), DATA_SEQUENCE_NUMBER(Integer.MAX_VALUE - 1001, "$data_sequence_number", BIGINT, PRIMITIVE), + SNAPSHOT_ID(Integer.MAX_VALUE - 1002, "$snapshot_id", BIGINT, PRIMITIVE), IS_DELETED(MetadataColumns.IS_DELETED.fieldId(), "$deleted", BOOLEAN, PRIMITIVE), DELETE_FILE_PATH(MetadataColumns.DELETE_FILE_PATH.fieldId(), "$delete_file_path", VARCHAR, PRIMITIVE), /** diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergPageSourceProvider.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergPageSourceProvider.java index 2a2460238edff..311b4b32c2f6a 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergPageSourceProvider.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergPageSourceProvider.java @@ -807,6 +807,9 @@ public ConnectorPageSource createPageSource( else if (icebergColumn.isDataSequenceNumberColumn()) { metadataValues.put(icebergColumn.getColumnIdentity().getId(), split.getDataSequenceNumber()); } + else if (icebergColumn.isSnapshotId()) { + metadataValues.put(icebergColumn.getColumnIdentity().getId(), split.getSnapshotId()); + } } List delegateColumns = columnsToReadFromStorage.stream().collect(toImmutableList()); diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplit.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplit.java index 2ebcdc5a8ed54..1f102783e06ff 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplit.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplit.java @@ -53,6 +53,7 @@ public class IcebergSplit private final long dataSequenceNumber; private final long affinitySchedulingFileSectionSize; private final long affinitySchedulingFileSectionIndex; + private final long snapshotId; @JsonCreator public IcebergSplit( @@ -69,7 +70,8 @@ public IcebergSplit( @JsonProperty("deletes") List deletes, @JsonProperty("changelogSplitInfo") Optional changelogSplitInfo, @JsonProperty("dataSequenceNumber") long dataSequenceNumber, - @JsonProperty("affinitySchedulingSectionSize") long affinitySchedulingFileSectionSize) + @JsonProperty("affinitySchedulingSectionSize") long affinitySchedulingFileSectionSize, + @JsonProperty("snapshotId") long snapshotId) { requireNonNull(nodeSelectionStrategy, "nodeSelectionStrategy is null"); this.path = requireNonNull(path, "path is null"); @@ -87,6 +89,7 @@ public IcebergSplit( this.dataSequenceNumber = dataSequenceNumber; this.affinitySchedulingFileSectionSize = affinitySchedulingFileSectionSize; this.affinitySchedulingFileSectionIndex = start / affinitySchedulingFileSectionSize; + this.snapshotId = snapshotId; } @JsonProperty @@ -184,6 +187,12 @@ public long getAffinitySchedulingFileSectionSize() return affinitySchedulingFileSectionSize; } + @JsonProperty + public long getSnapshotId() + { + return snapshotId; + } + @Override public Object getInfo() { diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplitManager.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplitManager.java index 0ad3345b7ae9d..25fd7357ec661 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplitManager.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplitManager.java @@ -93,7 +93,7 @@ public ConnectorSplitSource getSplits( .metricsReporter(new RuntimeStatsMetricsReporter(session.getRuntimeStats())) .fromSnapshotExclusive(fromSnapshot) .toSnapshot(toSnapshot); - return new ChangelogSplitSource(session, typeManager, icebergTable, scan); + return new ChangelogSplitSource(session, typeManager, icebergTable, scan, toSnapshot); } else if (table.getIcebergTableName().getTableType() == EQUALITY_DELETES) { CloseableIterable deleteFiles = IcebergUtil.getDeleteFiles(icebergTable, @@ -103,7 +103,7 @@ else if (table.getIcebergTableName().getTableType() == EQUALITY_DELETES) { table.getEqualityFieldIds(), session.getRuntimeStats()); - return new EqualityDeletesSplitSource(session, icebergTable, deleteFiles); + return new EqualityDeletesSplitSource(session, icebergTable, deleteFiles, table.getIcebergTableName().getSnapshotId().get()); } else { TableScan tableScan = icebergTable.newScan() diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplitSource.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplitSource.java index 98ee9f2693450..f586d94f58e62 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplitSource.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergSplitSource.java @@ -62,8 +62,8 @@ public class IcebergSplitSource private final long targetSplitSize; private final NodeSelectionStrategy nodeSelectionStrategy; private final long affinitySchedulingFileSectionSize; - private final TupleDomain metadataColumnConstraints; + private final long snapshotId; public IcebergSplitSource( ConnectorSession session, @@ -81,6 +81,7 @@ public IcebergSplitSource( closer.register(tableScan.planFiles()), targetSplitSize) .iterator()); + this.snapshotId = tableScan.snapshot().snapshotId(); } @Override @@ -143,6 +144,7 @@ private ConnectorSplit toIcebergSplit(FileScanTask task) task.deletes().stream().map(DeleteFile::fromIceberg).collect(toImmutableList()), Optional.empty(), getDataSequenceNumber(task.file()), - affinitySchedulingFileSectionSize); + affinitySchedulingFileSectionSize, + snapshotId); } } diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergTableHandle.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergTableHandle.java index 633f80d51eb33..8345583eecac3 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergTableHandle.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergTableHandle.java @@ -136,6 +136,21 @@ public IcebergTableHandle withUpdatedColumns(List updatedCo updatedColumns); } + public IcebergTableHandle withUpdatedIcebergTableName(IcebergTableName icebergTableName) + { + return new IcebergTableHandle( + getSchemaName(), + icebergTableName, + snapshotSpecified, + outputPath, + storageProperties, + tableSchemaJson, + partitionFieldIds, + equalityFieldIds, + sortOrder, + updatedColumns); + } + @Override public boolean equals(Object o) { diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/changelog/ChangelogSplitSource.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/changelog/ChangelogSplitSource.java index 44f6a2b30d494..c2d586abc0165 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/changelog/ChangelogSplitSource.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/changelog/ChangelogSplitSource.java @@ -73,12 +73,14 @@ public class ChangelogSplitSource private final List columnHandles; private final NodeSelectionStrategy nodeSelectionStrategy; private final long affinitySchedulingSectionSize; + private final long snapshotId; public ChangelogSplitSource( ConnectorSession session, TypeManager typeManager, Table table, - IncrementalChangelogScan tableScan) + IncrementalChangelogScan tableScan, + long snapshotId) { requireNonNull(session, "session is null"); requireNonNull(typeManager, "typeManager is null"); @@ -89,6 +91,7 @@ public ChangelogSplitSource( this.fileScanTaskIterable = closer.register(tableScan.planFiles()); this.fileScanTaskIterator = closer.register(fileScanTaskIterable.iterator()); this.affinitySchedulingSectionSize = getAffinitySchedulingFileSectionSize(session).toBytes(); + this.snapshotId = snapshotId; } @Override @@ -157,6 +160,7 @@ private IcebergSplit splitFromContentScanTask(ContentScanTask task, Ch changeTask.commitSnapshotId(), columnHandles)), getDataSequenceNumber(task.file()), - affinitySchedulingSectionSize); + affinitySchedulingSectionSize, + snapshotId); } } diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/equalitydeletes/EqualityDeletesSplitSource.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/equalitydeletes/EqualityDeletesSplitSource.java index a3df4ca65e049..15a15517237b6 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/equalitydeletes/EqualityDeletesSplitSource.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/equalitydeletes/EqualityDeletesSplitSource.java @@ -55,11 +55,13 @@ public class EqualityDeletesSplitSource private final Map specById; private final long affinitySchedulingSectionSize; private CloseableIterator deleteFiles; + private final long snapshotId; public EqualityDeletesSplitSource( ConnectorSession session, Table table, - CloseableIterable deleteFiles) + CloseableIterable deleteFiles, + long snapshotId) { this.session = requireNonNull(session, "session is null"); requireNonNull(table, "table is null"); @@ -67,6 +69,7 @@ public EqualityDeletesSplitSource( this.specById = table.specs(); this.deleteFiles = CloseableIterable.filter(deleteFiles, deleteFile -> fromIcebergFileContent(deleteFile.content()) == EQUALITY_DELETES).iterator(); this.affinitySchedulingSectionSize = getAffinitySchedulingFileSectionSize(session).toBytes(); + this.snapshotId = snapshotId; } @Override @@ -125,6 +128,7 @@ private IcebergSplit splitFromDeleteFile(DeleteFile deleteFile) ImmutableList.of(), Optional.empty(), IcebergUtil.getDataSequenceNumber(deleteFile), - affinitySchedulingSectionSize); + affinitySchedulingSectionSize, + snapshotId); } } diff --git a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/IcebergDistributedTestBase.java b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/IcebergDistributedTestBase.java index 5335a72caedc6..f59d458202448 100644 --- a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/IcebergDistributedTestBase.java +++ b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/IcebergDistributedTestBase.java @@ -2254,6 +2254,53 @@ public void testDeleteFilePathHiddenColumn() }); } + @Test + public void testSnapshotIdHiddenColumnSimple() + { + String tableName = "test_snapshot_id_hidden_" + randomTableSuffix(); + + assertUpdate("DROP TABLE IF EXISTS " + tableName); + + assertUpdate("CREATE TABLE " + tableName + " AS SELECT * FROM tpch.tiny.region WHERE regionkey=0", 1); + assertUpdate("INSERT INTO " + tableName + " SELECT * FROM tpch.tiny.region WHERE regionkey=1", 1); + Table icebergTable = loadTable(tableName); + + assertEquals( + computeActual("SELECT COUNT(DISTINCT \"$snapshot_id\") FROM " + tableName).getOnlyValue(), + 1L, + "Scan should return a single $snapshot_id"); + + Long snapshotIdFromQuery = (Long) computeActual("SELECT \"$snapshot_id\" FROM " + tableName + " LIMIT 1").getOnlyValue(); + assertEquals(snapshotIdFromQuery, icebergTable.currentSnapshot().snapshotId()); + } + + @Test + public void testSnapshotIdPredicatePushdown() + { + String tableName = "test_snapshot_id_pred_pushdown_" + randomTableSuffix(); + + assertUpdate("DROP TABLE IF EXISTS " + tableName); + + assertUpdate("CREATE TABLE " + tableName + "(id int, data varchar)"); + assertUpdate("INSERT INTO " + tableName + " VALUES (1, 'a')", 1); + + Long snapshotId = (Long) computeActual("SELECT \"$snapshot_id\" FROM " + tableName + " LIMIT 1").getOnlyValue(); + loadTable(tableName).refresh(); + + // Single value predicate + assertQuery("SELECT COUNT(*) FROM " + tableName + " WHERE \"$snapshot_id\" = " + snapshotId, "VALUES 1"); + + // Range predicate >= + assertQuery("SELECT COUNT(*) FROM " + tableName + " WHERE \"$snapshot_id\" >= " + snapshotId, "VALUES 1"); + + // Unsupported predicate + assertQueryFails("SELECT * FROM " + tableName + " WHERE \"$snapshot_id\" < " + snapshotId, + "Unsupported predicate for \\$snapshot_id; only >= constant is allowed"); + + // BETWEEN same value + assertQuery("SELECT COUNT(*) FROM " + tableName + " WHERE \"$snapshot_id\" BETWEEN " + snapshotId + " AND " + snapshotId, "VALUES 1"); + } + @Test(dataProvider = "equalityDeleteOptions") public void testEqualityDeletesWithDeletedHiddenColumn(String fileFormat, boolean joinRewriteEnabled) throws Exception diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.cpp b/presto-native-execution/presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.cpp index 3229da2e88d07..bf3af9742a848 100644 --- a/presto-native-execution/presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.cpp +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.cpp @@ -1156,6 +1156,8 @@ void to_json(json& j, const IcebergSplit& p) { "IcebergSplit", "int64_t", "affinitySchedulingSectionSize"); + to_json_key( + j, "snapshotId", p.snapshotId, "IcebergSplit", "int64_t", "snapshotId"); } void from_json(const json& j, IcebergSplit& p) { @@ -1235,6 +1237,8 @@ void from_json(const json& j, IcebergSplit& p) { "IcebergSplit", "int64_t", "affinitySchedulingSectionSize"); + from_json_key( + j, "snapshotId", p.snapshotId, "IcebergSplit", "int64_t", "snapshotId"); } } // namespace facebook::presto::protocol::iceberg namespace facebook::presto::protocol::iceberg { diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.h b/presto-native-execution/presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.h index 6696cd7ee5ded..e1913ad44919e 100644 --- a/presto-native-execution/presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.h +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.h @@ -252,6 +252,7 @@ struct IcebergSplit : public ConnectorSplit { std::shared_ptr changelogSplitInfo = {}; int64_t dataSequenceNumber = {}; int64_t affinitySchedulingSectionSize = {}; + int64_t snapshotId = {}; IcebergSplit() noexcept; };