Skip to content

[spark] Add managed Format Table partition administration#8730

Closed
sundapeng wants to merge 3 commits into
apache:masterfrom
sundapeng:split-v4/format-table-managed-spark-admin
Closed

[spark] Add managed Format Table partition administration#8730
sundapeng wants to merge 3 commits into
apache:masterfrom
sundapeng:split-v4/format-table-managed-spark-admin

Conversation

@sundapeng

@sundapeng sundapeng commented Jul 19, 2026

Copy link
Copy Markdown
Member

Relationship

Third part of splitting #8713; stacked on the DDL part #8729 (the diff shown here includes the
two previous commits until they merge — please review only the [spark] Add managed Format Table partition administration commit). Marked draft until the DDL part lands.

Purpose

Administration and repair on top of the DDL part: two procedures, MSCK REPAIR TABLE
and SHOW PARTITIONS.

Main changes

  • sys.list_format_table_partitions(table, where?, limit?, page_token?): paged listing.
    The continuation token is the catalog's own page token, passed through verbatim. With
    a where filter, each call returns the matching rows of raw catalog pages, skipping
    ahead past fully-filtered pages so an empty result always means the listing is
    exhausted; filtered pages can carry fewer than limit rows.
  • sys.sync_format_table_metadata(table, mode=ADD|DROP|SYNC, dry_run):
    filesystem-to-catalog reconciliation. dry_run defaults to true; discovery uses
    raw directory values (round-trips with writer-registered values) and fails on a
    mid-scan listing error
    instead of producing a truncated diff (a DROP diff from a
    truncated listing would unregister live partitions). Applies diffs in bounded batches;
    both directions converge on rerun. Spark cache is refreshed after any non-preview
    attempt, including ambiguous failures.
  • MSCK REPAIR TABLE [ADD|DROP|SYNC] PARTITIONS reuses the sync engine (bare MSCK =
    ADD, Hive semantics; DROP is metadata-only). Unmanaged Format Tables and native
    Paimon tables keep Spark's rejection.
  • SHOW PARTITIONS backed by the catalog, capped with a pointer to the paged procedure.

Behavior notes

This first version keeps the procedure surface minimal on purpose: no scope
restriction and no target parameter on the sync procedure (it always reconciles all
partition metadata, exactly like MSCK), and filtered listing pages are allowed to be
sparse instead of maintaining a resumable dense-page cursor. Both can be added later
without breaking the contract.

Tests

Procedure suite (26), MSCK end-to-end against a mock REST server (10), planning suite
extension (23), SHOW partitions exec tests (6).

Route managed Format Table partition discovery through the catalog so
scans read exactly the registered partitions and an empty registration
reads as empty instead of falling back to directory listing. Validate
partition locations against the table path before any read or delete.
Register written partitions at commit time in bounded batches, keep
IF NOT EXISTS registration idempotent for concurrent writers, and fall
back to unmanaged directory discovery when no catalog manages the
table.
Route ALTER TABLE ADD/DROP PARTITION for catalog-managed Format Tables
through a Spark-side partition gateway. ADD forwards the whole batch
with the IF NOT EXISTS flag so the catalog can apply it atomically and
creates partition directories; strict batch atomicity stays with the
catalog service. DROP unregisters partitions before deleting their
directories, expands partial specs through bounded catalog pagination,
and never touches data that is not registered. Session-level overrides
of the managed flag are ignored when classifying tables, and unmanaged
Format Tables fail with an explicit unsupported error.
Add list_format_table_partitions and sync_format_table_metadata
procedures for catalog-managed Format Tables. Listing pages through the
catalog and embeds a filter fingerprint in page tokens so stale cursors
are rejected. The sync procedure diffs the filesystem against the
catalog registration, defaults to dry-run, and applies repair diffs in
bounded batches. MSCK REPAIR TABLE reuses the same sync engine through
an interception ahead of Spark's v2 rejection, and SHOW PARTITIONS runs
through a bounded, paginated executor.
`MSCK REPAIR TABLE` fail with an error.

`SHOW PARTITIONS` throws an error when the number of partitions exceeds
`spark.paimon.format-table.show-partitions.max-results` (default: 10000). For larger tables, use

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.

Hive behavior?

remove the option, use `ALTER TABLE my_table UNSET TBLPROPERTIES ('metastore.partitioned-table')`.
On a REST catalog, an existing Format Table whose partitions were never registered reads as empty
until you register them with `MSCK REPAIR TABLE my_table` or
`CALL sys.sync_format_table_metadata`.

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.

Why not just use MSCK?

* catalog, or {@code null} if they can.
*/
@Nullable
private static String managedFormatTableLoadProblem(

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.

Just throw exception, remove this.

// Keyed by identifier full name: listings themselves live in per-instance caches, so sharing
// a generation counter across table incarnations (or across catalogs using the same name) can
// only cause an extra invalidation, never a stale read.
private static final Cache<String, AtomicLong> GENERATIONS =

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.

Remove this and all cache.

// after deserialization.
@Nullable private transient Catalog catalog;

public FormatTableCatalogProvider(Identifier identifier, CatalogLoader catalogLoader) {

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.

Just use CatalogLoader, remove this FormatTableCatalogProvider.

null);
}

public FormatTableCommit(

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.

Remove old constructor.

}
}

private RuntimeException partitionRegistrationFailure(RuntimeException cause) {

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.

Why need a method?

@sundapeng

Copy link
Copy Markdown
Member Author

Closing in favour of a re-split of this work.

The implementation changed enough since this split that updating the branch in
place would replace every line and leave the review comments pointing at code
that no longer exists:

  • the serializable provider with its 30s listing cache and JVM-wide generation
    counter is gone, replaced by a partition manager that creates one catalog per
    operation and closes it;
  • the managed scan subclass is gone, folded into FormatTableScan;
  • the two procedures are gone; MSCK REPAIR TABLE is the only entry point;
  • the feature no longer reuses metastore.partitioned-table. It has its own
    option, format-table.partition-source = filesystem | rest, so a
    catalog-level default set for Paimon tables cannot turn it on for a Format
    Table by accident.

The review comments here are all addressed; the new PRs describe how.

Replaced by:

@sundapeng sundapeng closed this Jul 20, 2026
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