[core] Introduce portable TableDescriptor for cross-language table construction#8819
[core] Introduce portable TableDescriptor for cross-language table construction#8819JunRuiLee wants to merge 1 commit into
Conversation
There is also a contract issue: the top-level |
463b20a to
d8bdaed
Compare
Thanks for the careful review, @JingsongLi! All three addressed:
One addition on top of the review: instead of rejecting non-main branches, v1 now supports a specific branch of a plain table — the branch travels in a dedicated branch field (omitted for main), and since schemaManager() is branch-scoped the persisted schema is read from the branch. Composite/fallback/chain tables remain out of scope. The reader side (paimon-rust) will be updated to consume this in its own PR once this contract lands. |
|
6829c77 to
3d7352e
Compare
…nstruction
Add org.apache.paimon.table.TableDescriptor (paimon-api) and
TableDescriptorSerializer (paimon-core): a slim, versioned JSON wire form that
serializes a resolved FileStoreTable into {path, full TableSchema, options} so a
non-Java reader (e.g. paimon-rust / paimon-cpp) can rebuild the table for
scan/read without a catalog lookup or JVM-only state. Non-main branches are
carried verbatim so a reader can fail fast rather than silently read main.
Motivated by the Doris Paimon-external-table integration (apache/doris#65883),
where the compute node re-resolves the table through a catalog; this lets it
consume the FE-planned table instead.
3d7352e to
c3cdb60
Compare
|
Thanks @JingsongLi. Now the serializer resolves the snapshot at serialize time (TimeTravelUtil.tryTravelToSnapshot) and carries only the resolved snapshotId (null for ordinary scans) — carrying the resolved id rather than raw scan.* avoids duplicating TimeTravelUtil.SCAN_KEYS / selector drift and keeps storage/sensitive options out. The reader (paimon-rust) will pin snapshotId in its own PR; on the split-read path the split already pins files. |
JingsongLi
left a comment
There was a problem hiding this comment.
I'm still a bit confused—why are we introducing this? Doesn't TableSchema alone suffice? The rest of the information seems to be in “Identifier” or “dynamic options,” all of which are related to the calculation engine.
Thanks, I think this concern is valid. I’ll discuss this direction with the Apache Doris community and follow up once we’ve aligned on the design. |
Purpose
Introduce a portable, versioned JSON description of a table —
TableDescriptor— so a non-Java runtime (e.g. a paimon-rust / paimon-cpp reader embedded in a compute engine) can rebuild a table for scan/read without a catalog lookup.Today a Java engine can serialize a
Tablevia native Java serialization, but that blob is not consumable by non-Java readers (it carries JVM-only state such asFileIO/CatalogEnvironment). As a result, an embedding engine has to re-resolve the table through a catalog on the reader side, which can observe a different schema/snapshot than the one the planner used, and ties the reader to a derived filesystem-catalog layout.This PR adds a slim, language-neutral contract that captures only what a reader needs:
org.apache.paimon.table.TableDescriptor(paimon-api,@Experimental):version,path, the fullTableSchema(identical to an on-diskschema/schema-N), optionaloptions/database/name/branch. Serialized throughJsonSerdeUtilso the nestedTableSchemauses Paimon's custom serde; unknown fields are ignored for forward compatibility; null fields are omitted to keep the payload slim.org.apache.paimon.table.TableDescriptorSerializer(paimon-core,@Experimental): builds a descriptor from a resolvedFileStoreTable(location()+schema()), and serializes it to JSON. A non-main branch is carried verbatim so a reader can fail fast rather than silently readmain; database/name must be set together or not at all.The reader side (in the paimon-rust cross-language reader) consumes the same JSON and reconstructs the table directly; a byte-identical golden fixture (
table-descriptor-v1.json) pins the wire form on both sides.Tests
TableDescriptorTest(paimon-api): JSON round-trip; nestedTableSchemauses Paimon's custom serde; unknown fields ignored.TableDescriptorSerializerTest(paimon-core): build from aFileStoreTable; round-trip; partial-identifier rejection; non-main branch carried through.TableDescriptorGoldenTest(paimon-core): producer output equals the checked-in canonical golden, and the golden parses back — the exact wire form the cross-language reader is tested against.API and Format
@Experimentalpublic API:TableDescriptor(paimon-api) andTableDescriptorSerializer(paimon-core).version = 1). No change to any existing on-disk or wire format.Documentation
None yet (experimental API). Docs can follow once the contract stabilizes.
Motivated by the Apache Doris Paimon-external-table integration (apache/doris#65883), where the compute node currently re-resolves the table through a catalog on the backend; this contract lets it consume the FE-planned table instead.