Skip to content

[Tracking][Catalog] Catalog SPI migration — decouple built-in connectors from FE core into loadable plugins #65185

Description

@morningman

Development branch:branch-catalog-spi — all migration PRs target this branch; it merges to master through #64304.

Background

Today Apache Doris FE hard-codes every external data source (hive, iceberg, paimon,
hudi, trino-connector, maxcompute, jdbc, es, …) inside fe/fe-core/.../datasource/,
wired into the catalog and planner layers through switch-case and
instanceof *ExternalTable checks. Adding or changing a connector means touching FE
core.

This tracking issue covers the effort to decouple each concrete connector into an
independent, loadable plugin module under fe/fe-connector/*
, leaving only generic
infrastructure and a stable catalog SPI bridge in fe-core.

End state: each connector ships as a self-contained plugin zip; fe-core has no
compile-time knowledge of any specific connector; the runtime discovers and loads
connectors through the catalog SPI (PluginDrivenExternalCatalog / …Table /
…ScanNode).

In scope: FE-side connector code under
datasource/{hive,iceberg,paimon,hudi,trinoconnector,maxcompute,jdbc,es,…}, plus the
reverse couplings (instanceof *ExternalTable, connector-specific sinks / scan-nodes)
scattered across nereids / planner / tablefunction / alter.

Out of scope: BE-side readers; fe-fs-spi file-system plugin work (separate
workstream); extension-spi; kafka / kinesis / odbc / Doris-to-Doris federation
(tracked separately). RemoteDoris stays an engine built-in catalog type; the
deprecated lakesoul type was removed rather than migrated (#65736).

Where the framework is documented

Prose docs now live in the tree and are the authoritative reference (they replaced the
branch's plan-doc/ corpus in #66251):

  • fe/fe-connector/README.md — architecture, module map, how a connector runs
    (startup / CREATE CATALOG routing / per-statement metadata / classloading /
    packaging), how to read the API, and a step-by-step "adding a new connector" guide.
  • fe/fe-connector/AGENTS.md — build & test recipes, the machine-checked obligations,
    and the invariants that no gate can express.

Design invariants (acceptance criteria)

These invariants must hold at every step:

  1. One-way dependencyfe-connector → fe-core. No connector module may
    import org.apache.doris.{catalog,common,datasource,qe,analysis,nereids,planner}.
    Enforced in the validate phase by build-support/check-fe-connector-imports.sh
    (self-test under build-support/tests/).
  2. Single metadata entry point. Inside fe-core, only PluginDrivenMetadata may
    call Connector#getMetadata; exempt call sites carry an explicit marker and
    deleting a marker auto-tightens the gate. Enforced by
    build-support/check-fe-core-metadata-funnel.sh ([perf](catalog) fe-connector-iceberg hot-path caching + fe-core per-statement metadata funnel, with session=user cache isolation #65785).
  3. Metadata backward compatibility. Old FE images holding GSON types such as
    IcebergExternalCatalog / PaimonExternalDatabase must deserialize and migrate
    transparently to PluginDrivenExternalCatalog. Verified by a unit-test suite whose
    fixtures are generated from real 4.1.3 bytecode ([test](catalog) verify 4.1.3 catalogs survive the connector-SPI cutover, with fixtures generated by real 4.1.3 bytecode #66214).
  4. No user-visible behavior regression. SHOW CREATE CATALOG, SHOW TABLE STATUS,
    information_schema.tables, EXPLAIN output, error messages, and catalog type /
    engine names are all preserved.

Progress — phases

Each phase lands as one or more PRs against branch-catalog-spi.

Supporting refactor & post-migration hardening (landed alongside / after the phases above):

Connector status

ConnectorTarget moduleStatusLanded in
jdbcfe-connector-jdbc✅ Done (SPI baseline / reference)pre-existing
esfe-connector-es✅ Done (SPI baseline / reference)pre-existing
trino-connectorfe-connector-trino✅ DoneP2 (#64096)
maxcomputefe-connector-maxcompute✅ DoneP4 (#64253, #64256)
paimonfe-connector-paimon✅ DoneP5 (#64446, #64653)
hudife-connector-hudi✅ DoneP3 (#64143), P7 (#65473)
icebergfe-connector-iceberg✅ DoneP6 (#64688)
hive (+HMS)fe-connector-hive / fe-connector-hms✅ DoneP7 (#65473)

Shared modules added for them (see the README's module map): fe-connector-metastore-api
/ -spi / -hms / -iceberg / -paimon (so a connector never hand-parses metastore
endpoint properties), fe-connector-cache, fe-connector-hms-hive-shade,
fe-connector-paimon-hive-shade, plus fe-kerberos and fe-trino-connector-common
outside this directory.

Upstream re-ports

The branch is rebased onto master continuously, and every upstream change to an
already-migrated datasource is re-ported onto the SPI rather than merged textually
(a textual merge would silently resurrect fe-core-side code paths that no longer run).
Re-ported so far: #63068, #64966, #65094, #65262, #65329, #65332, #65365, #65548,
#65676, #65782, #65784, #65834, #65870, #65904, #65955, #65984, #65991, #66004, #66008,
#66112.

User-visible changes at merge time

  • External catalogs are served by connector plugins, shipped as zips under
    fe/plugins/connector/ (Config.connector_plugin_root). Existing catalogs keep
    working across upgrade; no DDL change is required.
  • trino_connector_plugin_dir default moves from plugins/connectors to
    plugins/trino_plugins; the old directory is still read as a fallback.
  • The deprecated lakesoul catalog type is removed — creating or replaying one fails
    with Lakesoul catalog is no longer supported.

Remaining before #64304 can merge


This is an umbrella tracking issue; individual PRs reference it for detailed
per-phase design and review.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions