Skip to content

Spark 4.1: expose catalog labels via DESCRIBE - #18049

Draft
laskoviymishka wants to merge 2 commits into
mainfrom
laskoviymishka/labels-spark
Draft

laskoviymishka wants to merge 2 commits into
mainfrom
laskoviymishka/labels-spark

Conversation

@laskoviymishka

@laskoviymishka laskoviymishka commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Part of the catalog-labels work (spec: #15750).

Surfaces catalog-provided labels as table properties on the Spark table so they appear in DESCRIBE EXTENDED: object labels as labels.object.<key>, field labels as labels.field.<field-id>.<key>. If a label key collides with a stored table property, the label is shown under a de-conflicted key so both stay visible.

@github-actions github-actions Bot added the spark label Sep 10, 2026
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch from e393141 to 5c43066 Compare September 10, 2026 14:50
@laskoviymishka
laskoviymishka changed the base branch from laskoviymishka/labels-table to laskoviymishka/labels-metadata-table September 10, 2026 14:51
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch from 5c43066 to 7e89da2 Compare September 14, 2026 15:31
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-metadata-table branch from f985596 to 3067801 Compare September 14, 2026 15:31
Labels labels = ((SupportsLabels) table).labels();
labels
.objectLabels()
.forEach((key, value) -> propsBuilder.put(LABELS_OBJECT_PREFIX + key, value));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please handle collisions with stored table properties here. A table can already have a property such as labels.object.owner; if the catalog also supplies the owner label, both entries are added to the ImmutableMap.Builder, and build() throws, breaking DESCRIBE EXTENDED and SHOW TBLPROPERTIES. The field-label prefix has the same issue. Could we define precedence, filter conflicts, and add coverage for both prefixes?

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.

thx @szehon-ho, good catch, you're right that feeding both into one ImmutableMap.Builder throws and breaks DESCRIBE EXTENDED / SHOW TBLPROPERTIES.

My thinking: labels and table properties are genuinely different concepts, so ideally I'd surface catalog labels as their own section in DESCRIBE, separate from Table Properties. But DescribeTableExec doesn't allow it - the sections (schema, partitioning, metadata columns, detailed info, stats) are hardcoded, each tied to a specific SPI method, and properties() is the only channel a v2 connector has for arbitrary key-values (they all land in the single Table Properties blob). A dedicated "Labels" field in DESCRIBE isn't reachable from the connector side.

So as the pragmatic fallback I went with de-duplication, so neither is lost and DESCRIBE never fails:

  • a catalog label keeps its natural labels.object. / labels.field.. key when it's free;
  • if a stored property already holds that key, the label is surfaced under a de-conflicted ….catalog key (numeric suffix if that's also taken);
  • the stored property always keeps its own key.

Both stay visible and build() can't throw. Added coverage for the object and field prefixes.

For a properly separated, structured view, the queryable surface is the tbl.labels metadata table (scope / field_id / field_name / key / value), that's the authoritative place; the DESCRIBE properties are just at-a-glance visibility.

@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch from 7e89da2 to a812269 Compare September 17, 2026 15:02
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-metadata-table branch 2 times, most recently from c2f21e0 to 7d4bf56 Compare September 18, 2026 08:29
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch 2 times, most recently from cb995c5 to e2c01b6 Compare September 18, 2026 12:19
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-metadata-table branch from f0a6a5b to c59e1b2 Compare September 18, 2026 12:37
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch from e2c01b6 to ef7aeda Compare September 18, 2026 12:37
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-metadata-table branch from c59e1b2 to 3cb3e3b Compare September 18, 2026 13:03
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch from ef7aeda to 769261b Compare September 18, 2026 13:03
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-metadata-table branch from 3cb3e3b to 7b02ad2 Compare September 18, 2026 13:26
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch 3 times, most recently from 3e50307 to 1168368 Compare September 22, 2026 17:07
@szehon-ho

Copy link
Copy Markdown
Member

Thanks for addressing the collision issue. Looking at this again, Table.properties() is also used by Spark’s SHOW CREATE TABLE, so catalog-provided labels would be emitted as persisted TBLPROPERTIES.

I’m working on fixing this on the Spark side by separating display-only properties: apache/spark#59036. If accepted, Iceberg can expose labels through that API for supported Spark versions without affecting generated DDL.

@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch from 1168368 to d31b289 Compare September 30, 2026 20:20
@grundprinzip

Copy link
Copy Markdown

Extending the formatted DESCRIBE output of Spark tables is always a bit hard because it might break assumptions on how the content is parsed and unfortunately users aren't always doing a great job of dealing with new rows being added.

Instead of appending them as table properties directly, is there a potentially better way of plumbing the output through to the DESCRIBE table AS JSON output? So that we could add the labels in a structured way?

@laskoviymishka

Copy link
Copy Markdown
Contributor Author

@grundprinzip interesting topic.

I think @szehon-ho is already building the right Spark-side hook here: apache/spark#59036 adds Table.displayProperties(), a separate channel for transient catalog metadata like labels. It stays out of stored properties() and out of DDL / SHOW CREATE TABLE, so it doesn't leak into table state.

That's probably the right thing to build the Iceberg side on.

It would still show up in DESCRIBE EXTENDED as its own category. If the goal is a dedicated field in DESCRIBE ... AS JSON, that feels like a follow-up on top of #59036.

On the Iceberg side I'll hold this for now and rework it onto displayProperties() once that lands.

@szehon-ho

Copy link
Copy Markdown
Member

Yea the idea is to show them in DESCRIBE EXTENDED (not DESCRIBE).

Would that also break users in your view?
And if we want to do it, should it be part of the "Table Properties" Row as #18049 proposed, or another row like "Additional Properties"?

I think having this describe in another row in DESCRIBE AS JSON is a great idea too.

@szehon-ho

Copy link
Copy Markdown
Member

@grundprinzip any thoughts on us proceeding with this approach?

laskoviymishka and others added 2 commits October 13, 2026 18:34
Surface catalog-provided labels as reserved table properties on the Spark
table so they appear in DESCRIBE EXTENDED. The labels metadata table remains
the queryable counterpart.
Catalog labels and stored table properties can compute to the same key (e.g. a
stored `labels.object.owner` property and an `owner` object label). Feeding both
into one ImmutableMap.Builder threw on the duplicate key, breaking DESCRIBE
EXTENDED / SHOW TBLPROPERTIES. Accumulate into a mutable map and surface a
colliding label under a de-conflicted `.catalog` key, so the property and the
label both stay visible. Adds coverage for the object and field prefixes.

Co-authored-by: Isaac <[email protected]>
@laskoviymishka
laskoviymishka force-pushed the laskoviymishka/labels-spark branch from d31b289 to dfc44fd Compare October 13, 2026 17:43
@laskoviymishka
laskoviymishka removed this pull request from stack #18051 October 13, 2026 17:44
@laskoviymishka
laskoviymishka changed the base branch from laskoviymishka/labels-metadata-table to main October 13, 2026 17:44
@github-actions github-actions Bot added the stale label Nov 13, 2026
@apache apache deleted a comment from github-actions Bot Nov 13, 2026
@laskoviymishka
laskoviymishka marked this pull request as draft November 13, 2026 16:01
@laskoviymishka

Copy link
Copy Markdown
Contributor Author

Will wait for spark 4.4 support

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants