@@ -180,11 +180,9 @@ Its metadata files are retained. Use ``FilterAndCommit`` for batch recovery;
180180after a real-time error, recreate the writer and context and recover from durable
181181offsets as described by ``CommitWithProgress ``.
182182
183- Only the main branch is supported by ``WithCatalog ``. Both builders reject other
184- branches in the identifier or ``branch `` option; the write builder also checks
185- ``WithBranch ``. Explicit ``tbl$branch_main `` and ``branch=main `` are accepted.
186-
187- The current schema and latest snapshot need no files under the table path.
183+ The main branch's current schema and latest snapshot need no files under the table
184+ path. A branch needs its schema published under its own directory, while its
185+ latest snapshot can be held by the catalog alone, as described below.
188186A catalog response of ``{"snapshot": null} `` means the table has no snapshot.
189187Only a catalog reporting that snapshot loading is unsupported falls back to
190188file-system lookup; other catalog errors propagate to the caller.
@@ -193,7 +191,8 @@ Read ``Table::CatalogUuid()`` before preparing changes and pass it to
193191``WithTableId `` so the server can reject commits to a dropped and recreated table.
194192``Table::Uuid() `` can fall back to the table name and must not supply this id.
195193An unset table id is sent as null and subject to server validation. Each commit
196- attempt reloads the catalog's current schema id for the new snapshot.
194+ attempt to the main branch reloads the catalog's current schema id for the new
195+ snapshot; on a branch it reloads the id published under the branch.
197196
198197.. note ::
199198
@@ -224,7 +223,76 @@ restored by ``RollbackToAsLatest``. Serialize rollback and expiration through
224223the upstream coordinator: a rollback must finish before expiration starts,
225224so its restored file references are visible to the expiration operation.
226225
226+ .. warning ::
227+
228+ ``Expire `` returns ``NotImplemented `` before reading any snapshot or deleting
229+ any file when it runs on a branch other than main, or finds one under
230+ ``branch/branch-<name> `` of the table path. Data files are shared by every
231+ branch of the table, while expiration reads only the retained snapshots of the
232+ branch it runs on, so it could delete a file another branch still refers to.
233+ A branch the catalog holds without that directory, or one created while
234+ expiration runs, is not found: do not expire a table with such a branch, and
235+ serialize branch creation and expiration through the upstream coordinator.
236+
227237The C++ REST catalog covers the database, table, snapshot and commit operations
228238of the ``Catalog `` API. The parts of the Java REST catalog that have no C++
229239counterpart yet — altering a database or a table, views, functions, partitions,
230- tags, branch management and consumers — are not supported.
240+ tags, branch management and consumers — are not supported. Creating, deleting
241+ and merging a branch is what branch management covers; committing to a branch
242+ that already exists is supported, as described below.
243+
244+ Committing to a branch
245+ ~~~~~~~~~~~~~~~~~~~~~~
246+ This library creates no branch: one has to exist, with its schema published under
247+ ``branch/branch-<name> ``, before a write or a commit can be aimed at it.
248+
249+ Naming the branch
250+ ^^^^^^^^^^^^^^^^^
251+ A branch is addressed by the identifier of ``WithCatalog ``, which
252+ ``paimon::Identifier("db", "tbl", "dev") `` builds as ``tbl$branch_dev ``, so that
253+ the catalog answers for the branch: the snapshot it loads is the branch's, and
254+ the commit request is addressed to that branch by that identifier rather than by
255+ anything in its body. The ``branch `` option and, for writers, ``WithBranch `` may
256+ name the same branch as well; naming two different branches is rejected rather
257+ than resolved, and ``tbl$branch_main ``, ``branch=main `` and an empty name all
258+ mean the main branch. Naming a branch only in the option or ``WithBranch `` while
259+ the identifier names the bare table is rejected, as the catalog would then answer
260+ for the table while the files were written for the branch.
261+
262+ Names a catalog cannot tell apart from another object are rejected where a
263+ builder sees them: a name differing from ``main `` by case alone, such as
264+ ``tbl$branch_MAIN `` or ``branch=MAIN ``, which a catalog reads as the main branch
265+ while its snapshots go to a directory of their own; and a name holding a ``$ ``,
266+ such as ``branch=dev$options ``, which ``tbl$branch_dev$options `` reads back as
267+ the ``options `` system table of branch ``dev ``. ``paimon::Identifier("db",
268+ "tbl", "MAIN") `` never reaches that check: the constructor folds every spelling
269+ of ``main `` into the bare table name, as the Java client does, and so names the
270+ main branch.
271+
272+ What a branch keeps and what it shares
273+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
274+ A branch other than the main one publishes its schema and real-time offsets
275+ under ``branch/branch-<name> ``, where a snapshot written to the file system goes
276+ as well; the main branch keeps these files under the table path. A
277+ version-managed catalog can hold the latest snapshot of either branch alone.
278+ Data and manifests are shared by all branches under the table path,
279+ which is why expiration is not supported on a table with branches, as noted
280+ above.
281+
282+ A write or a commit aimed at a branch reads that schema rather than the
283+ catalog's, just as a read of that branch does, and asks the catalog for no schema
284+ at all, so a catalog serving only the table's own current schema still takes the
285+ branch's snapshots. The new snapshot records the schema id published there as
286+ well, which is the id a read of the branch resolves under
287+ ``branch/branch-<name> ``; only on the main branch is the recorded id the one the
288+ catalog reports, as its current schema may live nowhere else. Data files record
289+ the schema they were written with, as they do on the main branch.
290+
291+ Addressing a branch without a catalog client
292+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
293+ ``UseRESTCatalogCommit `` builds the request instead of sending it, and takes the
294+ branch from the ``branch `` option alone, as it is configured without an
295+ identifier. The request body carries the table id but no table name and no
296+ branch, so the branch has to appear in the URL the caller sends that body to:
297+ the commit endpoint of ``tbl$branch_dev ``, not the one of ``tbl ``. A body sent
298+ to the bare table's URL publishes the branch's snapshot on the main branch.
0 commit comments