Skip to content

feat: [iceberg] support iceberg metadata columns _file, _partition#4752

Draft
parthchandra wants to merge 12 commits into
apache:mainfrom
parthchandra:iceberg-metadata-columns
Draft

feat: [iceberg] support iceberg metadata columns _file, _partition#4752
parthchandra wants to merge 12 commits into
apache:mainfrom
parthchandra:iceberg-metadata-columns

Conversation

@parthchandra

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Adds support for iceberg metadata columns

Closes #.

Rationale for this change

What changes are included in this PR?

How are these changes tested?

@parthchandra
parthchandra force-pushed the iceberg-metadata-columns branch 2 times, most recently from d23bf63 to ec21656 Compare June 29, 2026 20:56
@parthchandra parthchandra changed the title feat: support iceberg metadata columns _file, _partition feat: [iceberg] support iceberg metadata columns _file, _partition Jun 29, 2026
@parthchandra
parthchandra force-pushed the iceberg-metadata-columns branch 2 times, most recently from 50fb6b3 to 0e34cf1 Compare July 6, 2026 18:23
@parthchandra
parthchandra force-pushed the iceberg-metadata-columns branch from cf7b59f to 82d7c43 Compare July 9, 2026 16:54
// Data under spec 0
spark.sql(s"INSERT INTO $table VALUES (1, 'US', 'A'), (2, 'EU', 'B')")

// Evolve partition spec: add category field -> spec 1

@hsiang-c hsiang-c Jul 9, 2026

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.

(nit) We might be able to use SparkSQL as well but it is not a must.

ALTER TABLE $table ADD PARTITION FIELD category; 

ref: https://iceberg.apache.org/docs/nightly/spark-ddl/#alter-table-add-partition-field

withFallbackReason(scan, "Comet Scan is not enabled")

case scan if metadataCols(scan).nonEmpty =>
case scan: FileSourceScanExec if metadataCols(scan).nonEmpty =>

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.

👍

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.

Maybe we can move it under the data source V1 branch?


// _pos should be 0-indexed per file
val result = spark.sql(s"SELECT id, _pos FROM $table ORDER BY id").collect()
assert(result(0).getLong(1) == 0L)

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.

Should be all zero according to my local test.

val positions = result.map(_.getLong(0))
// First file has 0,1,2; second file has 0,1 (or vice versa)
assert(positions.contains(0L))
assert(positions.count(_ == 0L) == 2, "Each file should start _pos at 0")

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.

I got this from Iceberg Java:

+----+
|_pos|
+----+
|0   |
|0   |
|0   |
|0   |
|0   |
+----+

@@ -1,5 +1,5 @@
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index db659dc06b..78f5e3440f 100644
index db659dc..78f5e34 100644

@hsiang-c hsiang-c Jul 10, 2026

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.

Nit, we need to use 10 digits hash: git config core.abbrev 10;

List<SparkPlan> batchScans = SparkPlanUtil.collectBatchScans(plan);
- assertThat(batchScans).hasSizeGreaterThan(0).allMatch(SparkPlan::supportsColumnar);
+ // When Comet is enabled, its native scan replaces BatchScanExec nodes entirely
+ assertThat(batchScans).allMatch(SparkPlan::supportsColumnar);

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.

LGTM

CTTY pushed a commit to apache/iceberg-rust that referenced this pull request Jul 16, 2026
## Which issue does this PR close?

<!--
We generally require a GitHub issue to be filed for all bug fixes and
enhancements and this helps us generate change logs for our releases.
You can link an issue to this PR using the GitHub syntax. For example
`Closes #123` indicates that this PR will close issue #123.
-->

- Partially closes #2607

## What changes are included in this PR?

<!--
Provide a summary of the modifications in this PR. List the main changes
such as new features, bug fixes, refactoring, or any other updates.
-->

- If a projection includes `_spec_id`, which is a constant like the
`_file` metadata column for all rows, add it to
`RecordBatchTransformerBuilder`


## Are these changes tested?

<!--
Specify what test covers (unit test, integration test, etc.).

If tests are not included in your PR, please explain why (for example,
are they covered by existing tests)?
-->

 - Yes, unit tests.
 - Iceberg Spark: apache/datafusion-comet#4752
 
Sample plan

```shell
== Physical Plan ==
AdaptiveSparkPlan isFinalPlan=false
+- CometSort [id#1247L, data#1248, _spec_id#1249], [id#1247L ASC NULLS FIRST]
   +- CometExchange rangepartitioning(id#1247L ASC NULLS FIRST, 200), ENSURE_REQUIREMENTS, CometNativeShuffle, [plan_id=3533]
      +- CometFilter [id#1247L, data#1248, _spec_id#1249], (id#1247L >= 10)
         +- CometIcebergNativeScan [id#1247L, data#1248, _spec_id#1249], /var/folders/d2/b93h6k7174ddqxltrxgb51040000gn/T/iceberg_warehouse16657344237870771906/iceberg_data/default/table/metadata/00004-70b616c5-1bbe-4e1d-bdd6-e9ac4910674a.metadata.json, testrest.default.table (branch=null) [filters=id IS NOT NULL, id >= 10, groupedBy=], 1
```
NoahKusaba pushed a commit to NoahKusaba/iceberg-rust that referenced this pull request Jul 16, 2026
## Which issue does this PR close?

<!--
We generally require a GitHub issue to be filed for all bug fixes and
enhancements and this helps us generate change logs for our releases.
You can link an issue to this PR using the GitHub syntax. For example
`Closes apache#123` indicates that this PR will close issue apache#123.
-->

- Partially closes apache#2607

## What changes are included in this PR?

<!--
Provide a summary of the modifications in this PR. List the main changes
such as new features, bug fixes, refactoring, or any other updates.
-->

- If a projection includes `_spec_id`, which is a constant like the
`_file` metadata column for all rows, add it to
`RecordBatchTransformerBuilder`


## Are these changes tested?

<!--
Specify what test covers (unit test, integration test, etc.).

If tests are not included in your PR, please explain why (for example,
are they covered by existing tests)?
-->

 - Yes, unit tests.
 - Iceberg Spark: apache/datafusion-comet#4752
 
Sample plan

```shell
== Physical Plan ==
AdaptiveSparkPlan isFinalPlan=false
+- CometSort [id#1247L, data#1248, _spec_id#1249], [id#1247L ASC NULLS FIRST]
   +- CometExchange rangepartitioning(id#1247L ASC NULLS FIRST, 200), ENSURE_REQUIREMENTS, CometNativeShuffle, [plan_id=3533]
      +- CometFilter [id#1247L, data#1248, _spec_id#1249], (id#1247L >= 10)
         +- CometIcebergNativeScan [id#1247L, data#1248, _spec_id#1249], /var/folders/d2/b93h6k7174ddqxltrxgb51040000gn/T/iceberg_warehouse16657344237870771906/iceberg_data/default/table/metadata/00004-70b616c5-1bbe-4e1d-bdd6-e9ac4910674a.metadata.json, testrest.default.table (branch=null) [filters=id IS NOT NULL, id >= 10, groupedBy=], 1
```
CTTY pushed a commit to apache/iceberg-rust that referenced this pull request Jul 20, 2026
## Which issue does this PR close?

<!--
We generally require a GitHub issue to be filed for all bug fixes and
enhancements and this helps us generate change logs for our releases.
You can link an issue to this PR using the GitHub syntax. For example
`Closes #123` indicates that this PR will close issue #123.
-->

- Partially closes #2607

## What changes are included in this PR?

<!--
Provide a summary of the modifications in this PR. List the main changes
such as new features, bug fixes, refactoring, or any other updates.
-->
- Support `_pos` metadata column by delegating it to the Parquet
reader's `RowNumber` virtual column, inspired by
apache/datafusion#22026.
- Refactor the `compare_schemas` function b/c `_pos` field id exists in
both `source_schema` and `target_schema` and the original implementation
might result in `SchemaComparison::NameChangesOnly`, which produces a
`RecordBatch` with correct content but incorrect column order.

## Are these changes tested?

<!--
Specify what test covers (unit test, integration test, etc.).

If tests are not included in your PR, please explain why (for example,
are they covered by existing tests)?
-->

 - Yes, unit tests.
 - Iceberg Spark: apache/datafusion-comet#4752

Sample plan

```shell
== Physical Plan ==
AdaptiveSparkPlan isFinalPlan=false
+- CometSort [id#863L, data#864, _pos#868L], [id#863L ASC NULLS FIRST]
   +- CometExchange rangepartitioning(id#863L ASC NULLS FIRST, 200), ENSURE_REQUIREMENTS, CometNativeShuffle, [plan_id=2634]
      +- CometFilter [id#863L, data#864, _pos#868L], (id#863L >= 10)
         +- CometIcebergNativeScan [id#863L, data#864, _pos#868L], file:/var/folders/d2/b93h6k7174ddqxltrxgb51040000gn/T/hive2622216829356851627/table/metadata/00004-95932e2b-bbe6-444e-81b8-069c5e748a20.metadata.json, spark_catalog.default.table (branch=null) [filters=id IS NOT NULL, id >= 10, groupedBy=], 1
```
@parthchandra
parthchandra force-pushed the iceberg-metadata-columns branch from e56d51d to 35f615b Compare July 20, 2026 23:43
@hsiang-c

Copy link
Copy Markdown
Contributor

Spark 4.2 fails probably b/c of #4969

@parthchandra

Copy link
Copy Markdown
Contributor Author

Spark 4.2 fails probably b/c of #4969

Thanks for the pointer @hsiang-c !

The iceberg runtime jar is needed for RESTCatalogHelper and
RESTCatalogAdapter to compile. The Spark 4.2 IncompatibleClassChangeError
is a pre-existing issue tracked by apache#4969.
@parthchandra
parthchandra force-pushed the iceberg-metadata-columns branch from dae0f75 to 393754e Compare July 21, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants