Skip to content

feat(inspect): support selecting columns in metadata table scans - #1008

Open
manuzhang wants to merge 1 commit into
apache:mainfrom
manuzhang:metadata-table-select-columns
Open

manuzhang wants to merge 1 commit into
apache:mainfrom
manuzhang:metadata-table-select-columns

Conversation

@manuzhang

Copy link
Copy Markdown
Member

Metadata table scans currently always return every column. Java's metadata tables support newScan().select(...): StaticDataTask projects each row to scan.schema(), so an engine running SELECT name FROM t.refs only gets name. This adds the same column selection to C++ metadata tables.

  • Add ColumnSelection (column names plus case sensitivity), MetadataTable::Scan(const ColumnSelection&), and TimeTravelMetadataTable::Scan(const SnapshotSelection&, const ColumnSelection&). Names resolve through Schema::Select, as in TableScanBuilder::Select: nested names are dot-concatenated, columns come back in schema order, * selects all columns, and unknown names are ignored (as in Java's Schema.select). An empty list returns rows without columns, which is enough to count rows.
  • Scan() is no longer virtual. Tables implement the protected ScanProjection(const Schema& projected_schema) instead, and ScanSnapshot also receives the projected schema.
  • Add inspect/metadata_table_columns_internal.h, which maps the projected columns to per-column append functions so a table builds only the selected columns. Selecting only some fields of a nested struct column returns NotSupported for now; no current metadata table has a struct column.
  • SnapshotsTable builds only the selected columns; for example, it no longer copies the summary map unless that column is selected. HistoryTable::Scan still returns NotSupported.

Open metadata table PRs (#876, #920, #1007) will need to override ScanProjection(const Schema&) instead of Scan().

Validation: pre-commit passed. All 18 metadata_table_test cases pass locally, including 8 new ones covering selection order, unknown names, case sensitivity, * and no selection, an empty selection, map columns, time-travel scans (using a recording test table), and HistoryTable. The changed public headers also compile as a C++20 consumer.

🤖 Generated with Claude Code

Add ColumnSelection and Scan overloads that return only the requested
columns, matching Java's metadata table select(). Names resolve through
Schema::Select, so nested names, case sensitivity, `*`, and unknown names
behave as in TableScanBuilder::Select.

Tables now implement ScanProjection(const Schema&) and build only the
selected columns. SnapshotsTable uses a per-column append table from the
new metadata_table_columns_internal.h helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 13, 2026 15:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

2 open findings
What changed in this PR

Adds column projection support to C++ Iceberg metadata table scans (including time travel), aligning behavior with Java (newScan().select(...)) and enabling engines to request only needed columns.

Changes:

  • Introduces ColumnSelection and overloads of MetadataTable::Scan(...) / TimeTravelMetadataTable::Scan(...) to project columns via Schema::Select.
  • Refactors scanning to be implemented via ScanProjection(const Schema&) / ScanSnapshot(..., const Schema&) instead of overriding Scan().
  • Adds internal helpers to map projected schema columns to per-column append functions, and updates SnapshotsTable + tests accordingly.
File Description
src/​iceberg/​inspect/​metadata_table.h Adds ColumnSelection and new Scan overloads; refactors scan implementation to ScanProjection / projected-schema time travel.
src/​iceberg/​inspect/​metadata_table.cc Implements column selection via Schema::Select and routes scans through projected schemas.
src/​iceberg/​inspect/​metadata_table_columns_internal.h New internal helper to select per-column append functions based on projected schema.
src/​iceberg/​inspect/​snapshots_table.h Updates SnapshotsTable to implement ScanProjection(...) rather than Scan().
src/​iceberg/​inspect/​snapshots_table.cc Implements projected-column building for snapshots using selected append functions.
src/​iceberg/​inspect/​history_table.h /​ .cc Updates HistoryTable to ScanProjection(...) while keeping scan unsupported.
src/​iceberg/​test/​snapshots_table_test.cc Adds tests for column selection semantics on SnapshotsTable.
src/​iceberg/​test/​metadata_table_test.cc Adds tests for time-travel scans with column projection and HistoryTable behavior.

🧠 Review effort: Lite


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +67 to +77
ICEBERG_CHECK(field.has_value(), "Metadata table column '{}' is not in the schema",
projected_field.name());
if (*field->get().type() != *projected_field.type()) {
return NotSupported("Cannot select nested fields of metadata table column '{}'",
projected_field.name());
}
auto column = std::ranges::find(columns, projected_field.field_id(),
&MetadataTableColumn<Row>::field_id);
ICEBERG_CHECK(column != columns.end(),
"Metadata table column '{}' has no append function",
projected_field.name());
EXPECT_EQ(batch->column_name(0), "summary");
ASSERT_EQ(batch->column(0)->type_id(), ::arrow::Type::MAP);
auto summaries = std::static_pointer_cast<::arrow::MapArray>(batch->column(0));
EXPECT_EQ(summaries->value_length(0), 10);

This branch has not been deployed

No deployments
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