[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. |
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.