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
2 changes: 1 addition & 1 deletion .github/trigger_files/IO_Iceberg_Integration_Tests.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"comment": "Modify this file in a trivial way to cause this test suite to run.",
"modification": 3
"modification": 1
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"comment": "Modify this file in a trivial way to cause this test suite to run.",
"modification": 2
"modification": 1
}
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
* Support for X source added (Java/Python) ([#X](https://github.com/apache/beam/issues/X)).
* Add ArrowFlight IO (Java) ([#20116](https://github.com/apache/beam/issues/20116)).
* (Python) JmsIO (IBM MQ, ActiveMQ, and other providers) is now supported in Python via cross-language ([#30716](https://github.com/apache/beam/issues/30716)).
* Added a full Iceberg batch and streaming changelog source (CDC) ([#38831](https://github.com/apache/beam/issues/38831))

## New Features / Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ public PCollectionRowTuple expand(PCollectionRowTuple input) {
.streaming(configuration.getStreaming())
.keeping(configuration.getKeep())
.dropping(configuration.getDrop())
.withFilter(configuration.getFilter());
.withFilter(configuration.getFilter())
.withWatermarkColumn(configuration.getWatermarkColumn())
.withWatermarkColumnTimeUnit(configuration.getWatermarkColumnTimeUnit())
.withMetadataColumns(configuration.getIncludeMetadataColumns());

@Nullable Integer pollIntervalSeconds = configuration.getPollIntervalSeconds();
if (pollIntervalSeconds != null) {
Expand Down Expand Up @@ -193,6 +196,26 @@ static Builder builder() {
"A subset of column names to exclude from reading. If null or empty, all columns will be read.")
abstract @Nullable List<String> getDrop();

@SchemaFieldDescription(
"Column used to derive the source's output watermark. "
+ "Must be an existing, required, top-level column of type 'long' or 'timestamp'. "
+ "If not set, the watermark advances according to snapshot commit timestamp.")
abstract @Nullable String getWatermarkColumn();

@SchemaFieldDescription(
"Time unit used to interpret watermark column of type LONG. One of NANOSECONDS, MICROSECONDS, "
+ "MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS. Defaults to MICROSECONDS.")
abstract @Nullable String getWatermarkColumnTimeUnit();

@SchemaFieldDescription(
"List of top-level metadata columns to include with CDC output rows. Supported columns: \n"
+ "- `_change_type`\n"
+ "- `_row_id`\n"
+ "- `_last_updated_sequence_number`\n"
+ "- `_commit_snapshot_id`\n"
+ "- `_commit_snapshot_sequence_number`\n")
abstract @Nullable List<String> getIncludeMetadataColumns();

@AutoValue.Builder
abstract static class Builder {
abstract Builder setTable(String table);
Expand Down Expand Up @@ -223,6 +246,12 @@ abstract static class Builder {

abstract Builder setFilter(String filter);

abstract Builder setWatermarkColumn(String watermarkColumn);

abstract Builder setWatermarkColumnTimeUnit(String timeUnit);

abstract Builder setIncludeMetadataColumns(List<String> metadataColumns);

abstract Configuration build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Map;
import org.apache.beam.sdk.annotations.Internal;
import org.apache.beam.sdk.io.Read;
import org.apache.beam.sdk.io.iceberg.cdc.IncrementalChangelogSource;
import org.apache.beam.sdk.options.StreamingOptions;
import org.apache.beam.sdk.schemas.Schema;
import org.apache.beam.sdk.transforms.PTransform;
Expand All @@ -33,6 +34,7 @@
import org.apache.beam.sdk.values.Row;
import org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.Preconditions;
import org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.Predicates;
import org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.collect.ImmutableList;
import org.apache.iceberg.DistributionMode;
import org.apache.iceberg.Table;
import org.apache.iceberg.catalog.Catalog;
Expand Down Expand Up @@ -576,6 +578,7 @@ public static ReadRows readRows(IcebergCatalogConfig catalogConfig) {
return new AutoValue_IcebergIO_ReadRows.Builder()
.setCatalogConfig(catalogConfig)
.setUseCdc(false)
.setMetadataColumns(ImmutableList.of())
.build();
}

Expand Down Expand Up @@ -612,6 +615,12 @@ public enum StartingStrategy {

abstract @Nullable String getFilter();

abstract @Nullable String getWatermarkColumn();

abstract @Nullable String getWatermarkColumnTimeUnit();

abstract List<String> getMetadataColumns();

abstract Builder toBuilder();

@AutoValue.Builder
Expand Down Expand Up @@ -642,6 +651,12 @@ abstract static class Builder {

abstract Builder setFilter(@Nullable String filter);

abstract Builder setWatermarkColumn(@Nullable String watermarkColumn);

abstract Builder setWatermarkColumnTimeUnit(@Nullable String timeUnit);

abstract Builder setMetadataColumns(List<String> metadataColumns);

abstract ReadRows build();
}

Expand Down Expand Up @@ -693,6 +708,31 @@ public ReadRows withFilter(@Nullable String filter) {
return toBuilder().setFilter(filter).build();
}

public ReadRows withWatermarkColumn(@Nullable String watermarkColumn) {
return toBuilder().setWatermarkColumn(watermarkColumn).build();
}

public ReadRows withWatermarkColumnTimeUnit(@Nullable String timeUnit) {
return toBuilder().setWatermarkColumnTimeUnit(timeUnit).build();
}

/**
* Appends top-level metadata columns to CDC output rows.
*
* <p>Supported values are {@code _change_type}, {@code _commit_snapshot_id}, {@code
* _commit_snapshot_sequence_number}, {@code _row_id}, and {@code
* _last_updated_sequence_number}. The row metadata columns are read from Iceberg data files and
* require a row-lineage table. The changelog metadata columns come from the emitted change kind
* and snapshot context and are appended when final Beam rows are emitted.
*
* <p>This option is only valid {@link #withCdc()}.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's fail if the incorrect combination is set.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It does in IcebergScanConfig#validate

*/
public ReadRows withMetadataColumns(@Nullable List<String> metadataColumns) {
return toBuilder()
.setMetadataColumns(metadataColumns == null ? ImmutableList.of() : metadataColumns)
.build();
}

@Override
public PCollection<Row> expand(PBegin input) {
TableIdentifier tableId =
Expand Down Expand Up @@ -728,12 +768,15 @@ public PCollection<Row> expand(PBegin input) {
.setKeepFields(getKeep())
.setDropFields(getDrop())
.setFilterString(getFilter())
.setWatermarkColumn(getWatermarkColumn())
.setWatermarkColumnTimeUnit(getWatermarkColumnTimeUnit())
.setMetadataColumns(getMetadataColumns())
.build();
scanConfig.validate(table);

PTransform<PBegin, PCollection<Row>> source =
getUseCdc()
? new IncrementalScanSource(scanConfig)
? new IncrementalChangelogSource(scanConfig)
: Read.from(new ScanSource(scanConfig));

return input.apply(source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,6 @@ public Expression getFilter() {
@Pure
public abstract @Nullable String getWatermarkColumnTimeUnit();

@Pure
public abstract @Nullable Duration getMaxSnapshotDiscoveryDelay();

@Pure
public abstract List<String> getMetadataColumns();

Expand Down Expand Up @@ -371,8 +368,6 @@ public abstract Builder setUpdateCompatibilityVersion(

public abstract Builder setWatermarkColumnTimeUnit(@Nullable String timeUnit);

public abstract Builder setMaxSnapshotDiscoveryDelay(@Nullable Duration delay);

public abstract Builder setMetadataColumns(List<String> metadataColumns);

public abstract IcebergScanConfig build();
Expand Down

This file was deleted.

This file was deleted.

Loading
Loading