Skip to content

refactor(table): split the table hierarchy and materialize the store a table serves - #447

Open
lucasfang wants to merge 30 commits into
apache:mainfrom
lucasfang:dev30
Open

lucasfang wants to merge 30 commits into
apache:mainfrom
lucasfang:dev30

Conversation

@lucasfang

@lucasfang lucasfang commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Purpose

Linked issue: close #459

The concrete Table mixed managed, format and system table construction, and operator creation repeatedly merged options and parsed storage configuration. This refactor makes a loaded table own the schema and storage configuration used by its operators.

  • Make Table an abstract interface implemented by FileStoreTable, FormatTable and the SystemTable family. Split managed behavior into append-only and primary-key implementations, with FileStore holding resolved CoreOptions and storage factories.
  • Separate table options from operation contexts. Use Table::Copy(options) to apply dynamic options and table->NewScan/NewRead/NewWrite/NewCommit(context) to create operators. Legacy static factories take Create(context, options) and load managed tables from context loading parameters.
  • Bind operator paths, schemas, file systems and scheme maps to the loaded table, including system-table views, fallback readers and dependency reads. Contexts provide execution settings and optional catalog services; write/commit identity checks remain enforced. Defer catalog file-system lookup from Builder::Finish() to table loading.
  • Replace LatestSchema() with GetSchema(), with no compatibility alias. The getter returns the bound schema; Catalog::GetTable() explicitly reloads the latest schema.
  • Validate immutable options and deletion-vector restrictions when copying. Preserve table identity and accumulated dynamic options; SwitchToBranch() explicitly loads the target branch schema. Snapshot/tag/timestamp copies select historical schemas and may perform metadata I/O.
  • Resolve time-travel metadata on the effective target branch after merging copy options. For example, Copy({branch=dev, scan.snapshot-id=1}) now uses dev's snapshot and schema together; it previously could bind main's historical fields while scanning dev. The shared helper also fixes system-table copies.
  • Preserve a format table's physical format when copying. Load REST global system tables locally and bind table-scoped system tables to their credential-bearing file systems.

Tests

Regression coverage includes option precedence, branch switching, immutable-option guards, historical schemas and field declarations, fallback schemas/options, format identity, system-table reads, per-table credentials, schema binding/reloading, and context loading versus execution settings.

The cross-branch regression was reproduced before the fix. It covers snapshot ID, tag and timestamp selection in both directions; empty/blank main aliases; managed tables and read-optimized views; copied schemas and actual data reads with default and explicit projections.

Local validation on the final code:

  • Full configured build passed.
  • All 69 focused Table/system-table tests passed.
  • All 6 related CTest targets passed: core, REST, scan, read, scan-and-read, and read compatibility. This includes all 2,541 core tests.
  • Changed-file pre-commit checks and git diff --check passed.

The complete 36-target CTest suite passed before the final cross-branch time-travel fix. The remaining 30 targets were not rerun after that focused fix. These results describe local validation.

cmake --build build -j 48
./build/debug/paimon-core-test --gtest_filter='TableTest.*:SystemTableTest.*'
ctest --test-dir build --output-on-failure -j 6 -R 'paimon-(core|rest|scan-and-read-inte|read-inte|scan-inte|paimon-read-compat-inte)-test'
pre-commit run --files <changed-files>
git diff --check

API and Format

Breaking public C++ API changes:

  • Table becomes abstract; format and system tables implement its common operator interface.
  • Static operator factories require a separate options map. Arbitrary context option maps and WithBranch() are removed.
  • GetSchema() replaces LatestSchema() without an alias.
  • Format-table copying uses virtual Copy(options); Location() becomes GetRootPath(). Managed branch APIs are exposed by FileStoreTable.

A loaded table retains its schema until explicitly reloaded or copied with a historical selector. Copy() and SwitchToBranch() have distinct schema-loading behavior. Snapshot, tag and timestamp selectors are supported; this does not implement every Java time-travel mode.

No storage format or wire protocol changes.

Documentation

Update public table/context API comments and the catalog and format-table user guides for operator construction, dynamic options, branch handling, bound schemas/storage, and deferred catalog credential lookup.

Generative AI tooling

Generated-by: Qoder

Generated-by: OpenAI Codex (GPT-6)

@lucasfang lucasfang changed the title refactor table refactor: refactor table abstraction Oct 20, 2026
@lucasfang
lucasfang marked this pull request as draft October 20, 2026 07:00
@lucasfang
lucasfang force-pushed the dev30 branch 2 times, most recently from f93aa25 to 7b35032 Compare October 23, 2026 07:06
@lucasfang lucasfang changed the title refactor: refactor table abstraction refactor(table): split the table hierarchy and materialize the store a table serves Oct 23, 2026
@lucasfang
lucasfang marked this pull request as ready for review October 23, 2026 09:32

@SteNicholas SteNicholas left a comment •

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.

@lucasfang, I left some comments for this pull request. PTAL.

Comment thread src/paimon/rest/rest_catalog.cpp Resolved
Comment thread src/paimon/core/table/file_store.h Resolved
Comment thread docs/source/user_guide/format_table.rst Resolved
Comment thread include/paimon/read_context.h Resolved
Comment thread src/paimon/core/table/file_store.h Resolved
Comment thread src/paimon/rest/rest_catalog.cpp Resolved

@SteNicholas SteNicholas left a comment •

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.

@lucasfang , one additional correctness issue remains in the direct system-table read path.

Comment thread include/paimon/catalog/table.h Resolved
Comment thread src/paimon/core/table/file_store.cpp Resolved

@zjw1111 zjw1111 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Two correctness issues remain in the table-first write/commit path at 13fba3780476ce4177d2197e0d7f62816bdd3047.

@zjw1111 zjw1111 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

One branch identity issue remains in SwitchToBranch() at 13fba3780476ce4177d2197e0d7f62816bdd3047.

@SteNicholas SteNicholas left a comment •

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.

@lucasfang, thanks for updates. Only one fallback-read correctness issue comment. PTAL.

@SteNicholas SteNicholas left a comment •

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.

@lucasfang, thanks for updates. I left three comments for correctness issues remaining at ba063c6: explicit context branch validation, dynamic options for system-table views, and accumulated overrides when copying to another branch.

Pass dynamic options explicitly to operator factories and use Table::Copy for table overrides. Align managed and system table copy behavior with Java, preserve historical schemas for time travel, guard incompatible options, and simplify new comments.

BREAKING CHANGE: operator contexts no longer accept dynamic options or WithBranch. Static operator Create calls require an options argument.
Expose the bound schema through GetSchema without a LatestSchema alias. Resolve catalog credentials only when loading tables and preserve bound storage settings for operators and dependency reads.

Resolve snapshot, tag, and historical schema metadata on the effective target branch. Cover cross-branch time travel with schema and data regressions.

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.

[Feature] Split the table hierarchy and materialize the store a table is served by

5 participants