This is an automated email from the ASF dual-hosted git repository.

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new e4e63a7a39c [refactor](catalog) remove per-data-source legacy types 
from fe-core (#66303)
e4e63a7a39c is described below

commit e4e63a7a39cd3ddf95180fc69d13c4eca0a318a1
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Fri Jul 31 17:40:53 2026 +0800

    [refactor](catalog) remove per-data-source legacy types from fe-core 
(#66303)
    
    ### What problem does this PR solve?
    
    Issue Number: close #xxx
    
    Related PR: #64304
    
    Problem Summary:
    
    Follow-up cleanup for #64304. After external catalogs moved behind the
    connector plugin SPI, fe-core still declared a name for every data
    source it no longer knows anything about. This removes those names:
    
    - **`TableIf.TableType`**: the per-source `*_EXTERNAL_TABLE` constants
    (`HMS`, `ES`, `JDBC`, `ICEBERG`, `PAIMON`, `MAX_COMPUTE`, `HUDI`,
    `TRINO_CONNECTOR`, `LAKESOUl`) and the deprecated internal-catalog
    `ICEBERG` / `HUDI`. An external table served by a connector plugin is a
    `PLUGIN_EXTERNAL_TABLE`; the source's own name is answered by
    `PluginDrivenExternalCatalog#getDisplayEngineName`, never by a mapping
    held in fe-core.
    - **`TableFormatType`**: `hive`, `iceberg`, `hudi`, `paimon`,
    `max_compute`, `transactional_hive`, `lakesoul`, `trino_connector`. A
    connector names its own format string through
    `ConnectorScanRange#getTableFormatType()`, which `PluginDrivenScanNode`
    forwards to BE verbatim. Only `tvf` and `remote_doris` are still
    produced by fe-core itself. The enum is not persisted anywhere — it only
    builds the thrift string.
    - **`InitDatabaseLog.Type`**, and with it `ExternalDatabase#dbLogType`,
    a field that was assigned and never read. `OP_INIT_EXTERNAL_DB` has been
    ignored on replay since 4.0 and `EditLog#logInitExternalDb` has no
    callers, so nothing writes one any more; the payload class stays only so
    `JournalEntity` can still consume such an entry out of an old journal.
    - **`InitCatalogLog.Type.HUDI`**, which was never produced: hudi tables
    have always lived in an hms catalog and no `HudiExternalCatalog` ever
    existed.
    - **`Database#discardHudiTable`**, dead once `TableType.HUDI` is gone.
    
    The remaining `InitCatalogLog.Type` values are kept on purpose. That
    enum is also the type of the persisted `ExternalCatalog#logType` field,
    which `PluginDrivenExternalCatalog#gsonPostProcess` reads to backfill
    the catalog type for the resource-backed catalogs (`es`, `jdbc`) that
    never persisted one. Deleting a name there would make it deserialize to
    `null` and lose that catalog's type on upgrade.
    
    **Upgrade compatibility.** An image written before the cutover still
    carries the old `TableType` names. It stays readable because the
    persisted table class is remapped by `GsonUtils`' compatible-subtype
    registry, and the stale `type` string deserializes to `null` — GSON
    returns `null` for an enum name it does not know rather than throwing —
    which `PluginDrivenExternalTable#gsonPostProcess` then normalizes to
    `PLUGIN_EXTERNAL_TABLE`, the same normalization it already applied to a
    recognized legacy name.
    
    Nothing in the compiler enforces that two-step property, and a
    regression would surface not as a build error but as an FE replaying a
    persisted external table with a `null` type. So the new
    `LegacyExternalTableTypeReplayTest` pins it for every deleted name,
    deliberately spelled as string literals so the constants cannot come
    back just to keep a test compiling.
---
 .../doris/connector/iceberg/IcebergScanRange.java  |  4 +-
 .../connector/iceberg/IcebergScanRangeTest.java    |  4 +-
 .../main/java/org/apache/doris/alter/Alter.java    |  7 --
 .../java/org/apache/doris/catalog/Database.java    | 16 ----
 .../java/org/apache/doris/catalog/TableIf.java     | 47 +++++-----
 .../doris/common/cache/NereidsSqlCacheManager.java |  1 -
 .../apache/doris/datasource/ExternalDatabase.java  |  6 +-
 .../doris/RemoteDorisExternalDatabase.java         |  3 +-
 .../infoschema/ExternalInfoSchemaDatabase.java     |  3 +-
 .../infoschema/ExternalMysqlDatabase.java          |  3 +-
 .../doris/datasource/log/InitCatalogLog.java       | 12 ++-
 .../doris/datasource/log/InitDatabaseLog.java      | 29 ++-----
 .../plugin/PluginDrivenExternalDatabase.java       |  5 +-
 .../doris/datasource/scan/TableFormatType.java     | 15 ++--
 .../datasource/test/TestExternalDatabase.java      |  3 +-
 .../doris/nereids/rules/analysis/BindRelation.java |  4 -
 .../plans/commands/ShowPartitionsCommand.java      |  4 +-
 .../PartitionValuesTableValuedFunction.java        |  1 -
 .../PartitionsTableValuedFunction.java             |  1 -
 .../LegacyExternalTableTypeReplayTest.java         | 99 ++++++++++++++++++++++
 .../doris/datasource/PluginDrivenSysTableTest.java |  9 +-
 21 files changed, 160 insertions(+), 116 deletions(-)

diff --git 
a/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergScanRange.java
 
b/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergScanRange.java
index 8e27898b249..a3aa736ed96 100644
--- 
a/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergScanRange.java
+++ 
b/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergScanRange.java
@@ -197,8 +197,8 @@ public class IcebergScanRange implements ConnectorScanRange 
{
 
     /**
      * The table-format-type string BE uses to select its Iceberg reader, 
mirroring paimon's
-     * {@code "paimon"}: the value of {@code TableFormatType.ICEBERG} (see 
fe-core
-     * {@code org.apache.doris.datasource.scan.TableFormatType}).
+     * {@code "paimon"}. The connector owns this string: fe-core forwards 
whatever it returns to BE, and
+     * holds no per-data-source format constant of its own.
      */
     @Override
     public String getTableFormatType() {
diff --git 
a/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergScanRangeTest.java
 
b/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergScanRangeTest.java
index 7f451815186..07f52b5d3a5 100644
--- 
a/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergScanRangeTest.java
+++ 
b/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergScanRangeTest.java
@@ -58,8 +58,8 @@ public class IcebergScanRangeTest {
         Assertions.assertEquals(8192L, range.getFileSize());
         Assertions.assertEquals("parquet", range.getFileFormat());
         // WHY: BE selects its iceberg reader off 
TTableFormatFileDesc.table_format_type, whose value for
-        // iceberg is "iceberg" (TableFormatType.ICEBERG). MUTATION: "paimon" 
/ "plugin_driven" -> BE routes
-        // the split to the wrong reader -> red.
+        // iceberg is "iceberg" -- a string this connector owns, since fe-core 
forwards it verbatim.
+        // MUTATION: "paimon" / "plugin_driven" -> BE routes the split to the 
wrong reader -> red.
         Assertions.assertEquals("iceberg", range.getTableFormatType());
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java 
b/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java
index a0f80327be2..0fca6040aa0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java
@@ -587,13 +587,6 @@ public class Alter {
             case ELASTICSEARCH:
                 processAlterExternalTable(command, (Table) tableIf, (Database) 
dbIf);
                 return;
-            case HMS_EXTERNAL_TABLE:
-            case JDBC_EXTERNAL_TABLE:
-            case ICEBERG_EXTERNAL_TABLE:
-            case PAIMON_EXTERNAL_TABLE:
-            case MAX_COMPUTE_EXTERNAL_TABLE:
-            case HUDI_EXTERNAL_TABLE:
-            case TRINO_CONNECTOR_EXTERNAL_TABLE:
             case PLUGIN_EXTERNAL_TABLE:
                 alterOps.addAll(command.getOps());
                 processAlterTableForExternalTable((ExternalTable) tableIf, 
alterOps);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
index ac6d53271f2..e59955c515b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
@@ -58,10 +58,8 @@ import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -715,24 +713,10 @@ public class Database extends MetaObject implements 
Writable, DatabaseIf<Table>,
 
     @Override
     public void write(DataOutput out) throws IOException {
-        discardHudiTable();
         Text.writeString(out, GsonUtils.GSON.toJson(this));
         writeTables(out);
     }
 
-
-    private void discardHudiTable() {
-        Iterator<Entry<String, Table>> iterator = 
nameToTable.entrySet().iterator();
-        while (iterator.hasNext()) {
-            Map.Entry<String, Table> entry = iterator.next();
-            if (entry.getValue().getType() == TableType.HUDI) {
-                LOG.warn("hudi table is deprecated, discard it. table name: 
{}", entry.getKey());
-                iterator.remove();
-                idToTable.remove(entry.getValue().getId());
-            }
-        }
-    }
-
     public void analyze() {
         for (Table table : nameToTable.values()) {
             table.analyze(getFullName());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/TableIf.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/TableIf.java
index a98aa7211bb..aee9b67ad61 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/TableIf.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/TableIf.java
@@ -229,8 +229,8 @@ public interface TableIf {
      */
     Set<Pair<String, String>> getColumnIndexPairs(Set<String> columns);
 
-    // Get all the chunk sizes of this table. Now, only HMS external table 
implemented this interface.
-    // For HMS external table, the return result is a list of all the files' 
size.
+    // Get all the chunk sizes of this table. Only a plugin-driven external 
table whose connector can list
+    // file sizes implements this; the return result is a list of all the 
files' size.
     List<Long> getChunkSizes();
 
     void write(DataOutput out) throws IOException;
@@ -260,15 +260,25 @@ public interface TableIf {
 
     /**
      * Doris table type.
+     *
+     * <p>There is no per-data-source external table type: an external table 
served by a connector plugin is a
+     * {@code PLUGIN_EXTERNAL_TABLE}, and the source's own name is answered by 
the connector
+     * ({@code PluginDrivenExternalCatalog#getDisplayEngineName}), never by a 
mapping held here.</p>
+     *
+     * <p>An image written before the cutover still carries the old per-source 
names, and stays readable:
+     * the persisted table class is remapped by {@code GsonUtils}' 
compatible-subtype registry, and the stale
+     * {@code type} string deserializes to {@code null} (Gson returns null for 
an enum name it does not know,
+     * it does not throw), which {@code 
PluginDrivenExternalTable#gsonPostProcess} then normalizes to
+     * {@code PLUGIN_EXTERNAL_TABLE} — the same normalization it already 
applied to a recognized legacy name.</p>
+     *
+     * <p>The legacy internal-catalog {@code CREATE EXTERNAL TABLE ... 
ENGINE=iceberg|hudi} types are gone as
+     * well: no {@code IcebergTable} / {@code HudiTable} class exists to carry 
them, and neither appears in the
+     * 4.1.3 GSON table registry ({@code upgrade/413/labels.tbl.txt}), so no 
readable image can hold one.
+     * {@code HIVE} stays because {@code HiveTable} is still registered 
there.</p>
      */
     enum TableType {
-        MYSQL, ODBC, OLAP, SCHEMA, INLINE_VIEW, VIEW, BROKER, ELASTICSEARCH, 
HIVE,
-        @Deprecated
-        ICEBERG, @Deprecated
-        HUDI, JDBC,
-        TABLE_VALUED_FUNCTION, HMS_EXTERNAL_TABLE, ES_EXTERNAL_TABLE, 
MATERIALIZED_VIEW, JDBC_EXTERNAL_TABLE,
-        ICEBERG_EXTERNAL_TABLE, TEST_EXTERNAL_TABLE, PAIMON_EXTERNAL_TABLE, 
MAX_COMPUTE_EXTERNAL_TABLE,
-        HUDI_EXTERNAL_TABLE, TRINO_CONNECTOR_EXTERNAL_TABLE, 
LAKESOUl_EXTERNAL_TABLE, DICTIONARY, DORIS_EXTERNAL_TABLE,
+        MYSQL, ODBC, OLAP, SCHEMA, INLINE_VIEW, VIEW, BROKER, ELASTICSEARCH, 
HIVE, JDBC,
+        TABLE_VALUED_FUNCTION, MATERIALIZED_VIEW, TEST_EXTERNAL_TABLE, 
DICTIONARY, DORIS_EXTERNAL_TABLE,
         PLUGIN_EXTERNAL_TABLE,
         STREAM;
 
@@ -290,25 +300,12 @@ public interface TableIf {
                     return "Broker";
                 case ELASTICSEARCH:
                     return "ElasticSearch";
-                case ES_EXTERNAL_TABLE:
-                    return "es";
                 case HIVE:
                     return "Hive";
-                case HUDI:
-                case HUDI_EXTERNAL_TABLE:
-                    return "Hudi";
                 case JDBC:
-                case JDBC_EXTERNAL_TABLE:
                     return "jdbc";
                 case TABLE_VALUED_FUNCTION:
                     return "Table_Valued_Function";
-                case HMS_EXTERNAL_TABLE:
-                    return "hms";
-                case ICEBERG:
-                case ICEBERG_EXTERNAL_TABLE:
-                    return "iceberg";
-                case PAIMON_EXTERNAL_TABLE:
-                    return "paimon";
                 case DICTIONARY:
                     return "dictionary";
                 case DORIS_EXTERNAL_TABLE:
@@ -346,15 +343,9 @@ public interface TableIf {
                 case BROKER:
                 case ELASTICSEARCH:
                 case HIVE:
-                case HUDI:
                 case JDBC:
-                case JDBC_EXTERNAL_TABLE:
                 case TABLE_VALUED_FUNCTION:
-                case HMS_EXTERNAL_TABLE:
-                case ICEBERG_EXTERNAL_TABLE:
-                case PAIMON_EXTERNAL_TABLE:
                 case MATERIALIZED_VIEW:
-                case TRINO_CONNECTOR_EXTERNAL_TABLE:
                 case DORIS_EXTERNAL_TABLE:
                 case PLUGIN_EXTERNAL_TABLE:
                     return "BASE TABLE";
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/cache/NereidsSqlCacheManager.java
 
b/fe/fe-core/src/main/java/org/apache/doris/common/cache/NereidsSqlCacheManager.java
index f965bbf0e38..bee844a9349 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/common/cache/NereidsSqlCacheManager.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/common/cache/NereidsSqlCacheManager.java
@@ -439,7 +439,6 @@ public class NereidsSqlCacheManager {
         for (Entry<FullTableName, TableVersion> scanTable : 
sqlCacheContext.getUsedTables().entrySet()) {
             TableVersion tableVersion = scanTable.getValue();
             if (tableVersion.type != TableType.OLAP && tableVersion.type != 
TableType.MATERIALIZED_VIEW
-                    && tableVersion.type != TableType.HMS_EXTERNAL_TABLE
                     && tableVersion.type != TableType.PLUGIN_EXTERNAL_TABLE) {
                 return IsChanged.CHANGED_AND_INVALIDATE_CACHE;
             }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
index 2b1281bdcf0..7b7207790bc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
@@ -33,7 +33,6 @@ import org.apache.doris.common.util.DebugPointUtil;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.datasource.infoschema.ExternalInfoSchemaDatabase;
 import org.apache.doris.datasource.infoschema.ExternalMysqlDatabase;
-import org.apache.doris.datasource.log.InitDatabaseLog;
 import org.apache.doris.datasource.metacache.MetaCache;
 import org.apache.doris.datasource.test.TestExternalDatabase;
 import org.apache.doris.persist.gson.GsonPostProcessable;
@@ -84,7 +83,6 @@ public abstract class ExternalDatabase<T extends 
ExternalTable>
     private Map<String, String> lowerCaseToTableName = Maps.newConcurrentMap();
     @SerializedName(value = "lastUpdateTime")
     protected long lastUpdateTime;
-    protected final InitDatabaseLog.Type dbLogType;
     protected ExternalCatalog extCatalog;
 
     private MetaCache<T> metaCache;
@@ -99,13 +97,11 @@ public abstract class ExternalDatabase<T extends 
ExternalTable>
      * @param name Database name.
      * @param remoteName Remote database name.
      */
-    public ExternalDatabase(ExternalCatalog extCatalog, long id, String name, 
String remoteName,
-            InitDatabaseLog.Type dbLogType) {
+    public ExternalDatabase(ExternalCatalog extCatalog, long id, String name, 
String remoteName) {
         this.extCatalog = extCatalog;
         this.id = id;
         this.name = name;
         this.remoteName = remoteName;
-        this.dbLogType = dbLogType;
     }
 
     public void setExtCatalog(ExternalCatalog extCatalog) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/doris/RemoteDorisExternalDatabase.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/doris/RemoteDorisExternalDatabase.java
index bd28a140807..bebaf752091 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/doris/RemoteDorisExternalDatabase.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/doris/RemoteDorisExternalDatabase.java
@@ -19,11 +19,10 @@ package org.apache.doris.datasource.doris;
 
 import org.apache.doris.datasource.ExternalCatalog;
 import org.apache.doris.datasource.ExternalDatabase;
-import org.apache.doris.datasource.log.InitDatabaseLog;
 
 public class RemoteDorisExternalDatabase extends 
ExternalDatabase<RemoteDorisExternalTable> {
     public RemoteDorisExternalDatabase(ExternalCatalog extCatalog, long id, 
String name, String remoteName) {
-        super(extCatalog, id, name, remoteName, 
InitDatabaseLog.Type.REMOTE_DORIS);
+        super(extCatalog, id, name, remoteName);
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalInfoSchemaDatabase.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalInfoSchemaDatabase.java
index 05425dc6eaa..bef82c0fe28 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalInfoSchemaDatabase.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalInfoSchemaDatabase.java
@@ -22,7 +22,6 @@ import org.apache.doris.catalog.SchemaTable;
 import org.apache.doris.datasource.ExternalCatalog;
 import org.apache.doris.datasource.ExternalDatabase;
 import org.apache.doris.datasource.ExternalTable;
-import org.apache.doris.datasource.log.InitDatabaseLog.Type;
 
 import com.google.common.collect.Lists;
 
@@ -36,7 +35,7 @@ public class ExternalInfoSchemaDatabase extends 
ExternalDatabase {
      * @param dbId The id of this database.
      */
     public ExternalInfoSchemaDatabase(ExternalCatalog extCatalog, long dbId) {
-        super(extCatalog, dbId, InfoSchemaDb.DATABASE_NAME, 
InfoSchemaDb.DATABASE_NAME, Type.INFO_SCHEMA_DB);
+        super(extCatalog, dbId, InfoSchemaDb.DATABASE_NAME, 
InfoSchemaDb.DATABASE_NAME);
     }
 
     public static List<String> listTableNames() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
index 20ef7c65149..a0f84696884 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
@@ -22,7 +22,6 @@ import org.apache.doris.catalog.MysqlDb;
 import org.apache.doris.datasource.ExternalCatalog;
 import org.apache.doris.datasource.ExternalDatabase;
 import org.apache.doris.datasource.ExternalTable;
-import org.apache.doris.datasource.log.InitDatabaseLog.Type;
 
 import com.google.common.collect.Lists;
 
@@ -36,7 +35,7 @@ public class ExternalMysqlDatabase extends ExternalDatabase {
      * @param dbId The id of this database.
      */
     public ExternalMysqlDatabase(ExternalCatalog extCatalog, long dbId) {
-        super(extCatalog, dbId, MysqlDb.DATABASE_NAME, MysqlDb.DATABASE_NAME, 
Type.INFO_SCHEMA_DB);
+        super(extCatalog, dbId, MysqlDb.DATABASE_NAME, MysqlDb.DATABASE_NAME);
     }
 
     public static List<String> listTableNames() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/log/InitCatalogLog.java 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/log/InitCatalogLog.java
index c7154c6413d..f97d5cd04c4 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/log/InitCatalogLog.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/log/InitCatalogLog.java
@@ -32,6 +32,17 @@ import java.util.List;
 
 @Data
 public class InitCatalogLog implements Writable {
+    /**
+     * Also the type of the persisted {@code ExternalCatalog#logType} field, 
which is why the per-data-source
+     * values stay even though only PLUGIN / REMOTE_DORIS / TEST are still 
produced: an image written before
+     * the connector cutover carries one of the old names, and
+     * {@code PluginDrivenExternalCatalog#gsonPostProcess} reads it to 
backfill the catalog's {@code type}
+     * property for the resource-backed catalogs (es, jdbc) that never 
persisted one. Deleting a name would
+     * make it deserialize to null and lose that catalog's type on upgrade.
+     *
+     * <p>HUDI is absent because it was never produced: hudi tables have 
always lived in an hms catalog and
+     * no {@code HudiExternalCatalog} ever existed, so no image can carry 
it.</p>
+     */
     public enum Type {
         HMS,
         ES,
@@ -39,7 +50,6 @@ public class InitCatalogLog implements Writable {
         ICEBERG,
         PAIMON,
         MAX_COMPUTE,
-        HUDI,
         LAKESOUL,
         TEST,
         TRINO_CONNECTOR,
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/log/InitDatabaseLog.java 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/log/InitDatabaseLog.java
index 1bfb4b7507b..a96edaff3c8 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/log/InitDatabaseLog.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/log/InitDatabaseLog.java
@@ -30,25 +30,16 @@ import java.io.DataOutput;
 import java.io.IOException;
 import java.util.List;
 
+/**
+ * Deserialize-only journal payload: {@code OP_INIT_EXTERNAL_DB} has been 
ignored on replay since 4.0 and
+ * nothing writes one any more ({@code EditLog#logInitExternalDb} has no 
callers). The class stays so that
+ * {@code JournalEntity} can still consume such an entry out of an old 
journal; its contents are discarded.
+ *
+ * <p>The former per-data-source {@code Type} enum is gone with it: its only 
other user was
+ * {@code ExternalDatabase#dbLogType}, a field that was assigned and never 
read.</p>
+ */
 @Data
 public class InitDatabaseLog implements Writable {
-    public enum Type {
-        HMS,
-        ICEBERG,
-        ES,
-        JDBC,
-        MAX_COMPUTE,
-        HUDI,
-        PAIMON,
-        LAKESOUL,
-        TEST,
-        INFO_SCHEMA_DB,
-        TRINO_CONNECTOR,
-        REMOTE_DORIS,
-        PLUGIN,
-        UNKNOWN;
-    }
-
     @SerializedName(value = "catalogId")
     private long catalogId;
 
@@ -76,9 +67,6 @@ public class InitDatabaseLog implements Writable {
     @SerializedName(value = "remoteTableNames")
     private List<String> remoteTableNames;
 
-    @SerializedName(value = "type")
-    private Type type;
-
     @SerializedName(value = "lastUpdateTime")
     protected long lastUpdateTime;
 
@@ -92,7 +80,6 @@ public class InitDatabaseLog implements Writable {
         createTableIds = Lists.newArrayList();
         createTableNames = Lists.newArrayList();
         remoteTableNames = Lists.newArrayList();
-        type = Type.UNKNOWN;
     }
 
     public void addRefreshTable(long id, String remoteName) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/plugin/PluginDrivenExternalDatabase.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/plugin/PluginDrivenExternalDatabase.java
index 8d32afa0187..761fffad76a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/plugin/PluginDrivenExternalDatabase.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/plugin/PluginDrivenExternalDatabase.java
@@ -24,7 +24,6 @@ import org.apache.doris.connector.api.ConnectorMetadata;
 import org.apache.doris.connector.api.ConnectorSession;
 import org.apache.doris.datasource.ExternalCatalog;
 import org.apache.doris.datasource.ExternalDatabase;
-import org.apache.doris.datasource.log.InitDatabaseLog;
 import org.apache.doris.datasource.mvcc.PluginDrivenMvccExternalTable;
 
 /**
@@ -37,12 +36,12 @@ public class PluginDrivenExternalDatabase extends 
ExternalDatabase<PluginDrivenE
 
     /** No-arg constructor for GSON deserialization. */
     public PluginDrivenExternalDatabase() {
-        super(null, 0, null, null, InitDatabaseLog.Type.PLUGIN);
+        super(null, 0, null, null);
     }
 
     public PluginDrivenExternalDatabase(ExternalCatalog extCatalog, long id,
             String name, String remoteName) {
-        super(extCatalog, id, name, remoteName, InitDatabaseLog.Type.PLUGIN);
+        super(extCatalog, id, name, remoteName);
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/scan/TableFormatType.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/scan/TableFormatType.java
index f9bc9c364fc..9cb90b4bec0 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/scan/TableFormatType.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/scan/TableFormatType.java
@@ -17,15 +17,14 @@
 
 package org.apache.doris.datasource.scan;
 
+/**
+ * The {@code TTableFormatFileDesc.table_format_type} values produced by 
fe-core itself.
+ *
+ * <p>A connector plugin names its own format string through {@code 
ConnectorScanRange#getTableFormatType()},
+ * which {@code PluginDrivenScanNode} forwards to BE verbatim, so no 
per-data-source constant belongs here.
+ * This enum is not persisted anywhere — it only builds the thrift string.</p>
+ */
 public enum TableFormatType {
-    HIVE("hive"),
-    ICEBERG("iceberg"),
-    HUDI("hudi"),
-    PAIMON("paimon"),
-    MAX_COMPUTE("max_compute"),
-    TRANSACTIONAL_HIVE("transactional_hive"),
-    LAKESOUL("lakesoul"),
-    TRINO_CONNECTOR("trino_connector"),
     TVF("tvf"),
     REMOTE_DORIS("remote_doris");
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalDatabase.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalDatabase.java
index d30f353c999..52e27296397 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalDatabase.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/test/TestExternalDatabase.java
@@ -19,12 +19,11 @@ package org.apache.doris.datasource.test;
 
 import org.apache.doris.datasource.ExternalCatalog;
 import org.apache.doris.datasource.ExternalDatabase;
-import org.apache.doris.datasource.log.InitDatabaseLog;
 
 public class TestExternalDatabase extends ExternalDatabase<TestExternalTable> {
 
     public TestExternalDatabase(ExternalCatalog extCatalog, long id, String 
name, String remoteName) {
-        super(extCatalog, id, name, remoteName, InitDatabaseLog.Type.TEST);
+        super(extCatalog, id, name, remoteName);
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
index 73a5bfd844a..53949892279 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
@@ -764,10 +764,6 @@ public class BindRelation extends OneAnalysisRuleFactory {
                     Plan viewBody = parseAndAnalyzeDorisView(view, 
qualifiedTableName, cascadesContext);
                     LogicalView<Plan> logicalView = new LogicalView<>(view, 
viewBody);
                     return new LogicalSubQueryAlias<>(qualifiedTableName, 
logicalView);
-                case PAIMON_EXTERNAL_TABLE:
-                case MAX_COMPUTE_EXTERNAL_TABLE:
-                case TRINO_CONNECTOR_EXTERNAL_TABLE:
-                case LAKESOUl_EXTERNAL_TABLE:
                 case PLUGIN_EXTERNAL_TABLE:
                     if (table instanceof PluginDrivenExternalTable
                             && ((PluginDrivenExternalTable) table).isView()) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowPartitionsCommand.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowPartitionsCommand.java
index 56c565e4c01..8107828fa92 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowPartitionsCommand.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowPartitionsCommand.java
@@ -241,9 +241,7 @@ public class ShowPartitionsCommand extends ShowCommand {
         }
 
         DatabaseIf db = catalog.getDbOrAnalysisException(dbName);
-        TableIf table = db.getTableOrMetaException(tblName, TableType.OLAP,
-                TableType.HMS_EXTERNAL_TABLE, 
TableType.MAX_COMPUTE_EXTERNAL_TABLE, TableType.PAIMON_EXTERNAL_TABLE,
-                TableType.PLUGIN_EXTERNAL_TABLE);
+        TableIf table = db.getTableOrMetaException(tblName, TableType.OLAP, 
TableType.PLUGIN_EXTERNAL_TABLE);
 
         if (!catalog.isInternalCatalog()) {
             if (!table.isPartitionedTable()) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/PartitionValuesTableValuedFunction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/PartitionValuesTableValuedFunction.java
index 2a53861fd3a..1a3c8045452 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/PartitionValuesTableValuedFunction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/PartitionValuesTableValuedFunction.java
@@ -124,7 +124,6 @@ public class PartitionValuesTableValuedFunction extends 
MetadataTableValuedFunct
         TableIf table;
         try {
             table = db.get().getTableOrMetaException(tableName, TableType.OLAP,
-                    TableType.HMS_EXTERNAL_TABLE, 
TableType.MAX_COMPUTE_EXTERNAL_TABLE,
                     TableType.PLUGIN_EXTERNAL_TABLE);
         } catch (MetaNotFoundException e) {
             throw new AnalysisException(e.getMessage(), e);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/PartitionsTableValuedFunction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/PartitionsTableValuedFunction.java
index e37575a302e..b58f2bed9ab 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/PartitionsTableValuedFunction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/PartitionsTableValuedFunction.java
@@ -178,7 +178,6 @@ public class PartitionsTableValuedFunction extends 
MetadataTableValuedFunction {
         TableIf table = null;
         try {
             table = db.get().getTableOrMetaException(tableName, TableType.OLAP,
-                    TableType.HMS_EXTERNAL_TABLE, 
TableType.MAX_COMPUTE_EXTERNAL_TABLE,
                     TableType.PLUGIN_EXTERNAL_TABLE);
         } catch (MetaNotFoundException e) {
             throw new AnalysisException(e.getMessage(), e);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/LegacyExternalTableTypeReplayTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/LegacyExternalTableTypeReplayTest.java
new file mode 100644
index 00000000000..8d005504592
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/LegacyExternalTableTypeReplayTest.java
@@ -0,0 +1,99 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.datasource;
+
+import org.apache.doris.catalog.TableIf;
+import org.apache.doris.catalog.TableIf.TableType;
+import org.apache.doris.datasource.mvcc.PluginDrivenMvccExternalTable;
+import org.apache.doris.datasource.plugin.PluginDrivenExternalTable;
+import org.apache.doris.persist.gson.GsonUtils;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Guards the OTHER half of edit-log compatibility for the SPI cutover. The 
{@code *GsonCompatReplayTest}
+ * family covers the persisted {@code "clazz"} discriminator; this covers the 
persisted {@code "type"} value,
+ * which is a {@link TableType} enum name serialized as a bare string.
+ *
+ * <p><b>Why this test exists:</b> the per-data-source {@code TableType} 
constants (HMS_EXTERNAL_TABLE,
+ * ICEBERG_EXTERNAL_TABLE, ...) were deleted so that fe-core holds no data 
source names, but an image written
+ * by a pre-cutover FE still contains those strings. Deleting a persisted enum 
constant is only safe because
+ * of a two-step property that nothing in the compiler enforces: GSON returns 
{@code null} (rather than
+ * throwing) for an enum name it does not know, and {@link 
PluginDrivenExternalTable#gsonPostProcess()} then
+ * normalizes whatever it got to {@code PLUGIN_EXTERNAL_TABLE}. If either step 
regresses, the failure is not
+ * a compile error but an FE that replays a persisted external table with a 
{@code null} type and NPEs (or
+ * silently misroutes it) on the next query — so it must be pinned by a test.
+ *
+ * <p>MUTATION: dropping the type normalization in {@code gsonPostProcess} 
leaves the restored type
+ * {@code null} -&gt; red for every legacy name below.</p>
+ */
+public class LegacyExternalTableTypeReplayTest {
+
+    /**
+     * Every per-source table type a pre-cutover FE could have written into an 
external table's {@code type}
+     * field, and which this branch no longer declares. Deliberately spelled 
as string literals: these names
+     * must NOT come back as constants just to keep a test compiling.
+     */
+    private static final String[] DELETED_LEGACY_TYPES = {
+            "HMS_EXTERNAL_TABLE",
+            "ES_EXTERNAL_TABLE",
+            "JDBC_EXTERNAL_TABLE",
+            "ICEBERG_EXTERNAL_TABLE",
+            "PAIMON_EXTERNAL_TABLE",
+            "MAX_COMPUTE_EXTERNAL_TABLE",
+            "HUDI_EXTERNAL_TABLE",
+            "TRINO_CONNECTOR_EXTERNAL_TABLE",
+            "LAKESOUl_EXTERNAL_TABLE",
+    };
+
+    @Test
+    public void deletedLegacyTypeNamesReplayAsPluginExternalTable() {
+        for (String legacyType : DELETED_LEGACY_TYPES) {
+            // Both targets of the compatible-subtype registry: the base class 
(es/jdbc/maxcompute/trino/
+            // lakesoul migrate here) and the MVCC variant (hms/iceberg/paimon 
migrate here).
+            assertReplaysAsPluginType(new PluginDrivenExternalTable(), 
legacyType);
+            assertReplaysAsPluginType(new PluginDrivenMvccExternalTable(), 
legacyType);
+        }
+    }
+
+    /**
+     * Round-trips a valid plugin-driven table through GSON, rewrites only the 
persisted {@code "type"} value
+     * to a legacy name (faithfully reproducing old-image bytes without 
depending on the deleted constants),
+     * then asserts the replay both survives and lands on {@code 
PLUGIN_EXTERNAL_TABLE}.
+     */
+    private void assertReplaysAsPluginType(PluginDrivenExternalTable table, 
String legacyType) {
+        table.id = 7L;
+        table.name = "legacy_tbl";
+        table.dbName = "legacy_db";
+        table.type = TableType.PLUGIN_EXTERNAL_TABLE;
+
+        String needle = "\"type\":\"PLUGIN_EXTERNAL_TABLE\"";
+        String json = GsonUtils.GSON.toJson(table, TableIf.class);
+        // Sanity: the type must actually be persisted, or rewriting it below 
would prove nothing.
+        Assertions.assertTrue(json.contains(needle),
+                "expected " + needle + " in serialized json: " + json);
+        String legacyJson = json.replace(needle, "\"type\":\"" + legacyType + 
"\"");
+
+        TableIf restored = GsonUtils.GSON.fromJson(legacyJson, TableIf.class);
+        Assertions.assertSame(table.getClass(), restored.getClass(),
+                "a legacy '" + legacyType + "' type value must not change 
which class replays");
+        Assertions.assertEquals(TableType.PLUGIN_EXTERNAL_TABLE, 
restored.getType(),
+                "a table persisted as '" + legacyType + "' must replay as 
PLUGIN_EXTERNAL_TABLE, not null");
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/PluginDrivenSysTableTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/PluginDrivenSysTableTest.java
index 92a1b1c5526..31bbdcc55a0 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/PluginDrivenSysTableTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/PluginDrivenSysTableTest.java
@@ -290,12 +290,11 @@ public class PluginDrivenSysTableTest {
         PluginDrivenSysExternalTable sys = new 
PluginDrivenSysExternalTable(base, "snapshots");
 
         // WHY: information_schema.tables.TABLE_TYPE for an iceberg sys table 
(e.g. tbl$snapshots) must read
-        // "BASE TABLE", byte-identical to a legacy ICEBERG_EXTERNAL_TABLE. 
The sys table inherits
-        // PLUGIN_EXTERNAL_TABLE and routes getMysqlType -> 
TableType.toMysqlType; the same-test pin of
-        // ICEBERG_EXTERNAL_TABLE.toMysqlType proves new == legacy with no 
Env. MUTATION: deleting the
+        // "BASE TABLE", byte-identical to what a legacy 
ICEBERG_EXTERNAL_TABLE reported. The sys table inherits
+        // PLUGIN_EXTERNAL_TABLE and routes getMysqlType -> 
TableType.toMysqlType. The legacy type constant is
+        // gone, so the legacy answer is pinned here as the frozen literal it 
always was. MUTATION: deleting the
         // PLUGIN_EXTERNAL_TABLE case in TableIf.TableType.toMysqlType -> sys 
getMysqlType returns null -> red.
-        Assertions.assertEquals("BASE TABLE", sys.getMysqlType());
-        Assertions.assertEquals("BASE TABLE", 
TableType.ICEBERG_EXTERNAL_TABLE.toMysqlType(),
+        Assertions.assertEquals("BASE TABLE", sys.getMysqlType(),
                 "the new plugin sys path must match the legacy iceberg 
TABLE_TYPE");
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to