Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions api/src/main/java/org/apache/iceberg/BatchScan.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.apache.iceberg;

import java.util.function.Supplier;
import org.apache.iceberg.io.FileIO;

/** API for configuring a batch scan. */
Expand Down Expand Up @@ -73,7 +74,7 @@ public interface BatchScan extends Scan<BatchScan, ScanTask, ScanTaskGroup<ScanT

/** Returns the {@link FileIO} instance to use when reading data files for this scan. */
@Override
default FileIO io() {
return table().io();
default Supplier<FileIO> fileIO() {
return table()::io;
}
}
5 changes: 3 additions & 2 deletions api/src/main/java/org/apache/iceberg/BatchScanAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import org.apache.iceberg.expressions.Expression;
import org.apache.iceberg.io.CloseableIterable;
import org.apache.iceberg.io.FileIO;
Expand All @@ -40,8 +41,8 @@ public Table table() {
}

@Override
public FileIO io() {
return scan.io();
public Supplier<FileIO> fileIO() {
return scan.fileIO();
}

@Override
Expand Down
5 changes: 3 additions & 2 deletions api/src/main/java/org/apache/iceberg/Scan.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import org.apache.iceberg.expressions.Expression;
import org.apache.iceberg.io.CloseableIterable;
import org.apache.iceberg.io.FileIO;
Expand Down Expand Up @@ -211,7 +212,7 @@ default ThisT minRowsRequested(long numRows) {
}

/** Returns the {@link FileIO} instance to use when reading data files for this scan. */
default FileIO io() {
throw new UnsupportedOperationException("io() is not implemented: added in 1.11.0");
default Supplier<FileIO> fileIO() {
throw new UnsupportedOperationException("fileIO() is not implemented: added in 1.11.0");
}
}
13 changes: 11 additions & 2 deletions core/src/main/java/org/apache/iceberg/BaseScan.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.iceberg.expressions.Binder;
import org.apache.iceberg.expressions.Expression;
Expand Down Expand Up @@ -102,11 +103,19 @@ public Table table() {
return table;
}

@Override
public FileIO io() {
/**
* @deprecated since 1.11.0, will be removed in 1.12.0; use {@link BaseScan#fileIO()} instead.
*/
@Deprecated
protected FileIO io() {
return table.io();
}

@Override
public Supplier<FileIO> fileIO() {
return table::io;
}

protected Schema tableSchema() {
return schema;
}
Expand Down
11 changes: 7 additions & 4 deletions core/src/main/java/org/apache/iceberg/rest/RESTTableScan.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.iceberg.CatalogProperties;
import org.apache.iceberg.CatalogUtil;
Expand Down Expand Up @@ -129,10 +130,12 @@ protected TableScan newRefinedScan(
}

@Override
public FileIO io() {
Preconditions.checkState(
null != scanFileIO, "FileIO is not available: planFiles() must be called first");
return scanFileIO;
public Supplier<FileIO> fileIO() {
return () -> {
Preconditions.checkState(
Copy link
Contributor Author

@nastra nastra Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rdblue we could consider removing this check, wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do feel like there's an argument that we should still keep the check. The Supplier return type indicates to a caller that they need to think about when to invoke get but if the caller does invoke get prematurely, I think it's best to throw rather than return null.

null != scanFileIO, "FileIO is not available: planFiles() must be called first");
return scanFileIO;
};
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -996,18 +996,20 @@ public <T extends RESTResponse> T execute(
assertThat(table.io().properties()).doesNotContainKey(RESTCatalogProperties.REST_SCAN_PLAN_ID);

TableScan tableScan = table.newScan();
assertThatThrownBy(tableScan::io)
assertThatThrownBy(() -> tableScan.fileIO().get())
.isInstanceOf(IllegalStateException.class)
.hasMessage("FileIO is not available: planFiles() must be called first");

// make sure remote scan planning is called and FileIO gets the planId
assertThat(tableScan.planFiles()).hasSize(1);
assertThat(table.io().properties()).doesNotContainKey(RESTCatalogProperties.REST_SCAN_PLAN_ID);
assertThat(tableScan.io().properties()).containsKey(RESTCatalogProperties.REST_SCAN_PLAN_ID);
String planId = tableScan.io().properties().get(RESTCatalogProperties.REST_SCAN_PLAN_ID);
assertThat(tableScan.fileIO().get().properties())
.containsKey(RESTCatalogProperties.REST_SCAN_PLAN_ID);
String planId =
tableScan.fileIO().get().properties().get(RESTCatalogProperties.REST_SCAN_PLAN_ID);

TableScan newScan = table.newScan();
assertThatThrownBy(newScan::io)
assertThatThrownBy(() -> newScan.fileIO().get())
.isInstanceOf(IllegalStateException.class)
.hasMessage("FileIO is not available: planFiles() must be called first");

Expand All @@ -1016,8 +1018,9 @@ public <T extends RESTResponse> T execute(
assertThat(table.io().properties()).doesNotContainKey(RESTCatalogProperties.REST_SCAN_PLAN_ID);

// make sure planIds are different for each scan
assertThat(newScan.io().properties()).containsKey(RESTCatalogProperties.REST_SCAN_PLAN_ID);
assertThat(newScan.io().properties().get(RESTCatalogProperties.REST_SCAN_PLAN_ID))
assertThat(newScan.fileIO().get().properties())
.containsKey(RESTCatalogProperties.REST_SCAN_PLAN_ID);
assertThat(newScan.fileIO().get().properties().get(RESTCatalogProperties.REST_SCAN_PLAN_ID))
.isNotEqualTo(planId);
}

Expand Down
Loading