Repository navigation
[Feature](iceberg) Support Iceberg JDBC Catalog - #59502
Conversation
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
There was a problem hiding this comment.
Pull request overview
This PR adds support for Iceberg JDBC Catalog, enabling metadata storage in relational databases (PostgreSQL, MySQL, SQLite) as an alternative to HMS or other catalog types. The implementation follows the existing pattern used by other Iceberg catalog types and integrates seamlessly with Doris's catalog framework.
Key Changes:
- Added JDBC catalog type with comprehensive property handling and S3-compatible storage support
- Integrated JDBC catalog into factory registration and serialization infrastructure
- Added unit tests for property validation and JDBC-specific configuration passthrough
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| IcebergJdbcMetaStoreProperties.java | Core implementation handling JDBC catalog properties, URI configuration, and storage integration |
| IcebergJdbcExternalCatalog.java | External catalog class following standard pattern for JDBC catalog type |
| IcebergJdbcMetaStorePropertiesTest.java | Unit tests validating property handling, passthrough, and required field checks |
| IcebergPropertiesFactory.java | Registered "jdbc" catalog type in the factory |
| IcebergExternalCatalogFactory.java | Added JDBC catalog creation in the factory switch statement |
| GsonUtils.java | Registered IcebergJdbcExternalCatalog for JSON serialization |
| IcebergScanNode.java | Added JDBC catalog type to supported scan sources |
| IcebergExternalCatalog.java | Added ICEBERG_JDBC constant definition |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private static void toFileIOProperties(List<StorageProperties> storagePropertiesList, | ||
| Map<String, String> fileIOProperties, Configuration conf) { | ||
| for (StorageProperties storageProperties : storagePropertiesList) { | ||
| if (storageProperties instanceof AbstractS3CompatibleProperties) { | ||
| toS3FileIOProperties((AbstractS3CompatibleProperties) storageProperties, fileIOProperties); | ||
| } else if (storageProperties.getHadoopStorageConfig() != null) { | ||
| conf.addResource(storageProperties.getHadoopStorageConfig()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static void toS3FileIOProperties(AbstractS3CompatibleProperties s3Properties, | ||
| Map<String, String> options) { | ||
| // Set S3FileIO as the FileIO implementation for S3-compatible storage | ||
| options.put(CatalogProperties.FILE_IO_IMPL, "org.apache.iceberg.aws.s3.S3FileIO"); | ||
|
|
||
| if (StringUtils.isNotBlank(s3Properties.getEndpoint())) { | ||
| options.put(S3FileIOProperties.ENDPOINT, s3Properties.getEndpoint()); | ||
| } | ||
| if (StringUtils.isNotBlank(s3Properties.getUsePathStyle())) { | ||
| options.put(S3FileIOProperties.PATH_STYLE_ACCESS, s3Properties.getUsePathStyle()); | ||
| } | ||
| if (StringUtils.isNotBlank(s3Properties.getRegion())) { | ||
| options.put(AwsClientProperties.CLIENT_REGION, s3Properties.getRegion()); | ||
| } | ||
| if (StringUtils.isNotBlank(s3Properties.getAccessKey())) { | ||
| options.put(S3FileIOProperties.ACCESS_KEY_ID, s3Properties.getAccessKey()); | ||
| } | ||
| if (StringUtils.isNotBlank(s3Properties.getSecretKey())) { | ||
| options.put(S3FileIOProperties.SECRET_ACCESS_KEY, s3Properties.getSecretKey()); | ||
| } | ||
| if (StringUtils.isNotBlank(s3Properties.getSessionToken())) { | ||
| options.put(S3FileIOProperties.SESSION_TOKEN, s3Properties.getSessionToken()); | ||
| } | ||
| } |
There was a problem hiding this comment.
The methods toFileIOProperties and toS3FileIOProperties are duplicated from IcebergRestProperties with only minor differences (the problematic FILE_IO_IMPL line). Consider extracting these common methods to the AbstractIcebergProperties base class to eliminate code duplication and ensure consistency across all Iceberg catalog implementations. This would make maintenance easier and prevent similar issues in the future.
| // Set S3FileIO as the FileIO implementation for S3-compatible storage | ||
| options.put(CatalogProperties.FILE_IO_IMPL, "org.apache.iceberg.aws.s3.S3FileIO"); | ||
|
|
There was a problem hiding this comment.
Setting FILE_IO_IMPL unconditionally to S3FileIO when S3 storage is detected may break functionality for non-S3 storage types. Looking at IcebergRestProperties, the toS3FileIOProperties method does not set FILE_IO_IMPL and relies on Iceberg's automatic FileIO selection via CatalogUtil.buildIcebergCatalog. This line should be removed to maintain consistency with other catalog implementations and allow Iceberg to handle FileIO selection automatically based on the storage properties provided.
| // Set S3FileIO as the FileIO implementation for S3-compatible storage | |
| options.put(CatalogProperties.FILE_IO_IMPL, "org.apache.iceberg.aws.s3.S3FileIO"); |
| private String uri = ""; | ||
|
|
||
| @ConnectorProperty( | ||
| names = {"jdbc.user"}, |
There was a problem hiding this comment.
How about adding iceberg. prefix to all properties?
| private String jdbcStrictMode; | ||
|
|
||
| @ConnectorProperty( | ||
| names = {"driver_url"}, |
There was a problem hiding this comment.
| names = {"driver_url"}, | |
| names = {"iceberg.driver-url"}, |
I know it is diff from JDBC catalog's prop, but we need to keep name consistency within this iceberg jdbc catalog.
| private String driverUrl; | ||
|
|
||
| @ConnectorProperty( | ||
| names = {"driver_class"}, |
There was a problem hiding this comment.
| names = {"driver_class"}, | |
| names = {"iceberg.driver-class"}, |
| private String jdbcPassword; | ||
|
|
||
| @ConnectorProperty( | ||
| names = {"jdbc.init-catalog-tables"}, |
There was a problem hiding this comment.
For init-catalog-tables, schema-version and strict-mode, do we have default values for these config?
There was a problem hiding this comment.
yes,init-catalog-tables=true,schema-version=v0,strict-mode=false
|
run buildall |
TPC-H: Total hot run time: 31726 ms |
TPC-DS: Total hot run time: 172056 ms |
ClickBench: Total hot run time: 26.96 s |
FE UT Coverage ReportIncrement line coverage |
|
run buildall |
FE UT Coverage ReportIncrement line coverage |
TPC-H: Total hot run time: 32120 ms |
TPC-DS: Total hot run time: 172679 ms |
ClickBench: Total hot run time: 26.69 s |
|
run buildall |
TPC-H: Total hot run time: 32014 ms |
TPC-DS: Total hot run time: 175551 ms |
ClickBench: Total hot run time: 26.79 s |
FE Regression Coverage ReportIncrement line coverage |
|
run buildall |
TPC-H: Total hot run time: 31461 ms |
FE UT Coverage ReportIncrement line coverage |
TPC-DS: Total hot run time: 172303 ms |
ClickBench: Total hot run time: 27.81 s |
FE Regression Coverage ReportIncrement line coverage |
|
PR approved by at least one committer and no changes requested. |
|
PR approved by anyone and no changes requested. |
### What problem does this PR solve? Problem Summary: Currently, Doris supports multiple Iceberg catalog types (HMS, REST, Hadoop, Glue, DLF, S3Tables) but lacks support for JDBC Catalog. This PR adds support for Iceberg JDBC Catalog, which allows users to store Iceberg metadata in relational databases like PostgreSQL, MySQL, and SQLite. **Key Changes:** - Added `IcebergJdbcMetaStoreProperties` class to handle JDBC catalog configurations - Added `IcebergJdbcExternalCatalog` class for JDBC catalog operations - Integrated JDBC catalog with existing Iceberg framework (factory registration, Gson serialization) - Added support for all storage systems (S3, HDFS, OSS, etc.) with JDBC catalog - Added proper S3FileIO configuration for S3-compatible storage **Benefits:** - Provides an alternative metadata storage option using relational databases - Supports database transactions for better concurrency control - Easier deployment compared to HMS for users without existing Hive infrastructure - Better integration with existing database infrastructure
### What problem does this PR solve? Problem Summary: Currently, Doris supports multiple Iceberg catalog types (HMS, REST, Hadoop, Glue, DLF, S3Tables) but lacks support for JDBC Catalog. This PR adds support for Iceberg JDBC Catalog, which allows users to store Iceberg metadata in relational databases like PostgreSQL, MySQL, and SQLite. **Key Changes:** - Added `IcebergJdbcMetaStoreProperties` class to handle JDBC catalog configurations - Added `IcebergJdbcExternalCatalog` class for JDBC catalog operations - Integrated JDBC catalog with existing Iceberg framework (factory registration, Gson serialization) - Added support for all storage systems (S3, HDFS, OSS, etc.) with JDBC catalog - Added proper S3FileIO configuration for S3-compatible storage **Benefits:** - Provides an alternative metadata storage option using relational databases - Supports database transactions for better concurrency control - Easier deployment compared to HMS for users without existing Hive infrastructure - Better integration with existing database infrastructure
### What problem does this PR solve? Problem Summary: Currently, Doris supports multiple Iceberg catalog types (HMS, REST, Hadoop, Glue, DLF, S3Tables) but lacks support for JDBC Catalog. This PR adds support for Iceberg JDBC Catalog, which allows users to store Iceberg metadata in relational databases like PostgreSQL, MySQL, and SQLite. **Key Changes:** - Added `IcebergJdbcMetaStoreProperties` class to handle JDBC catalog configurations - Added `IcebergJdbcExternalCatalog` class for JDBC catalog operations - Integrated JDBC catalog with existing Iceberg framework (factory registration, Gson serialization) - Added support for all storage systems (S3, HDFS, OSS, etc.) with JDBC catalog - Added proper S3FileIO configuration for S3-compatible storage **Benefits:** - Provides an alternative metadata storage option using relational databases - Supports database transactions for better concurrency control - Easier deployment compared to HMS for users without existing Hive infrastructure - Better integration with existing database infrastructure
### What problem does this PR solve? Issue Number: close #xxx Related PR: #59502 Problem Summary: Doris initialized Iceberg JDBC Catalog with the Doris local catalog name. Iceberg JDBC Catalog uses the SDK catalog initialization name as the `catalog_name` isolation key in JDBC metadata tables, so a Doris catalog named differently from the writer catalog, such as Spark `spark_catalog`, could not list namespaces or tables written under that remote `catalog_name`. This PR adds required `iceberg.jdbc.catalog_name` for Iceberg JDBC catalog and uses it as the Iceberg SDK catalog initialization name. The Doris local catalog name remains independent and continues to be used for Doris namespace/table identifier semantics.
### What problem does this PR solve? Issue Number: close #xxx Related PR: #59502 Problem Summary: Doris initialized Iceberg JDBC Catalog with the Doris local catalog name. Iceberg JDBC Catalog uses the SDK catalog initialization name as the `catalog_name` isolation key in JDBC metadata tables, so a Doris catalog named differently from the writer catalog, such as Spark `spark_catalog`, could not list namespaces or tables written under that remote `catalog_name`. This PR adds required `iceberg.jdbc.catalog_name` for Iceberg JDBC catalog and uses it as the Iceberg SDK catalog initialization name. The Doris local catalog name remains independent and continues to be used for Doris namespace/table identifier semantics.
### What problem does this PR solve? Issue Number: close #xxx Related PR: apache#59502 Problem Summary: Doris initialized Iceberg JDBC Catalog with the Doris local catalog name. Iceberg JDBC Catalog uses the SDK catalog initialization name as the `catalog_name` isolation key in JDBC metadata tables, so a Doris catalog named differently from the writer catalog, such as Spark `spark_catalog`, could not list namespaces or tables written under that remote `catalog_name`. This PR adds required `iceberg.jdbc.catalog_name` for Iceberg JDBC catalog and uses it as the Iceberg SDK catalog initialization name. The Doris local catalog name remains independent and continues to be used for Doris namespace/table identifier semantics.
…udit text ### Background SHOW CREATE CATALOG, SHOW CATALOG, the `catalogs()` table function and the audit text of CREATE CATALOG replace a property value with `*XXX` when `DatasourcePrintableMap.isSensitiveKey` matches its key. Until now the keys came from a list in fe-core and from the keys filesystem plugins report at startup. A connector plugin marks its secret properties `sensitive = true`, but that mark only masks the connector's own log lines. A connector tells the engine about its security-relevant properties through `ConnectorProvider#securitySurface()`. ### What problem does this PR solve? Issue Number: None Related PR: apache#69588 (added the connector security surface this extends), apache#45164 (introduced the unmasked ALTER CATALOG audit text), apache#27115 (masked it for the statement apache#45164 replaced), apache#59502 (added `iceberg.jdbc.password`), apache#54523 (added the Paimon REST DLF keys), apache#65730 (branch-4.1's Lance catalog, whose REST secrets the Lance port will declare on this surface) PR Type: Bugfix Problem Summary: Catalog secrets that only a connector knows are on no masking list, so SHOW CREATE CATALOG and the other renderings print them in clear: `iceberg.jdbc.password`, `paimon.jdbc.password`, the Paimon REST DLF key pair, `mc.access_key`, and credentials passed through under `trino.` or `adbc.`. Separately, `ALTER CATALOG ... SET PROPERTIES` is written to the audit log unmasked, whatever the key. Each connector now declares its secrets on its security surface, taken from its `sensitive` marks, and the surface can also declare a namespace of secret keys for options passed through unread; Fluss's lake options were hard-coded in fe-core for that reason. The engine masks the union, with fe-core's own list kept as the floor. ALTER CATALOG is masked like CREATE CATALOG. ### Details - **Change map:** 42 files, +1035 −76 over two commits: production code +376 −48, tests +645 −24, the connector README +13 −3, the plugin API version in `fe/fe-connector/pom.xml`. The first commit adds secret keys to the surface (reviewed alone before). The second does the rest: 1. Key namespaces on the SPI: `withSensitiveKeyPrefix` and `SensitiveKeyPrefix.covers`, which holds the matching rule; a collection form of `withSensitiveKeys` (`ConnectorSecuritySurface`, +130). 2. Engine: `isSensitiveKey` matches registered namespaces, the Fluss rule becomes one of them; `ConnectorPluginManager` registers them and reads every surface before it publishes a provider (+70). 3. Connectors: every provider declares its secrets; `MetaStoreProviders.sensitivePropertyKeys()` gives the union of a plugin's metastore backends; `IcebergJdbcMetaStoreProvider` reports its keys like its siblings; the keytab paths lose their `sensitive` mark (+140). 4. ALTER CATALOG audit masking (+16). - **Frequency:** Always. Create or alter a catalog that sets one of the keys above, then run SHOW CREATE CATALOG, SHOW CATALOG `<name>` or `select * from catalogs()`, or read the audit log after an ALTER CATALOG ... SET PROPERTIES. - **Root cause:** `isSensitiveKey` consulted only fe-core's list and the filesystem providers' keys. A connector's `sensitive` marks fed only `toMaskedString`; `MetaStoreProvider.sensitivePropertyKeys()` existed for this, but nothing called it, and the Iceberg JDBC backend did not implement it. For ALTER CATALOG, `AlterCatalogPropertiesCommand` does not implement `NeedAuditEncryption` and `LogicalPlanBuilderForEncryption` has no `visitAlterCatalogProperties`, so `AuditLogHelper` records the original text; the statement it replaced in apache#45164 was masked by apache#27115. - **Why existing tests missed it:** Unit tests: `DatasourcePrintableMapTest` checks fe-core's own keys, the provider surface tests checked only the SSRF and driver_url keys, and `EncryptSQLTest` and `RepositoryAuditEncryptionTest` cover CREATE CATALOG, repositories and resources but not ALTER CATALOG. Regression: `audit/test_external_catalog_credential_masking` creates only Iceberg REST catalogs, whose keys are on fe-core's list, and never alters one. - **Fix:** The engine must not name a connector's properties, so the connectors declare their secrets, from the same `sensitive` marks that mask their logs; jdbc and es declare both spellings their legacy prefix allows, and trino and adbc declare the namespace they pass through, a key there being a secret when its rest names `key`, `secret`, `password`, `token` or `credential` (also `authorization` for ADBC). fe-core keeps the connector keys it lists, so a catalog whose plugin is not loaded masks what it masked before. A provider whose `securitySurface()` throws at startup is skipped, as a filesystem provider is, instead of stopping FE. - **Other paths and branches:** Fixed here: every rendering above and FE's statement logging, which share `isSensitiveKey` and `NeedAuditEncryption`. Not covered, since a key name cannot express them safely: raw Iceberg SDK keys copied through (`token`, `credential`), Paimon options re-keyed from `paimon.*`, Hadoop `fs.*` keys, and secrets inside a URL. The ALTER CATALOG gap is on branch-4.0, 4.1 and 4.2 (from apache#45164); branch-3.1 still uses the masked statement. branch-4.1 and 4.2 also print the connector keys above in clear; without the connector SPI their fix differs and is tracked separately. - **Behavior change:** The namespaces also mask non-secrets whose names carry those words, such as `trino.hive.s3.aws-access-key` or a keystore path. Keytab paths, which no release masks, are no longer masked in connector log lines: marked `sensitive`, `hadoop.kerberos.keytab` would be masked in every storage vault and resource. ### Testing All runs were local (macOS), on master `f5c993f2c94` plus this change: - Regression `audit/test_external_catalog_credential_masking`, extended with an Iceberg JDBC catalog: SHOW CREATE CATALOG masks `iceberg.jdbc.password`, and the audit texts of its CREATE CATALOG and of an ALTER CATALOG that sets the password and `s3.secret_key` hold only `*XXX`. Against the local cluster's FE without this change it fails at the first new check, SHOW CREATE CATALOG printing the password; with a FE built from this change it passes. - fe-connector-spi: all 160 tests, with the refreshed surface baseline (+4 lines); the metastore modules: all tests; ten connector modules: 29 classes, 511 tests, including each connector's surface test, which checks real key names. - fe-core: 26 classes, 341 tests, including `ConnectorPluginManagerTest`, `DatasourcePrintableMapTest`, `EncryptSQLTest` and the audit and plugin gate tests; 14 of them again after the last change to registration. - Twenty mutations, each caught by its test: for example, reverting either half of the ALTER CATALOG fix (`EncryptSQLTest` sees the statement in clear), matching a marker anywhere in the key, an empty metastore union, or re-marking a keytab. ### Notes for Reviewers - `SensitiveKeyPrefix.covers` lives on the SPI so that a connector's test can check its declaration against real key names and the engine applies the same rule; the Fluss floor in fe-core uses it too. - The entries both fe-core and a connector declare are deliberate: the floor is frozen, as the comment in `DatasourcePrintableMap` says. - The plugin API stays at 31.0, the first commit's bump. Hudi declares nothing: it owns no catalog properties. ### Release note SHOW CREATE CATALOG, SHOW CATALOG, the `catalogs()` table function and the audit log now mask `iceberg.jdbc.password`, `paimon.jdbc.password`, `paimon.rest.dlf.access-key-id`, `paimon.rest.dlf.access-key-secret`, `mc.access_key`, and the `trino.*` and `adbc.*` properties whose names carry `key`, `secret`, `password`, `token` or `credential` (`authorization` too for `adbc.*`). ALTER CATALOG ... SET PROPERTIES statements are masked in the audit log like CREATE CATALOG. ### Check List (For Author) - Behavior changed: Yes (see Details) - Does this need documentation: No - Pre-submission status: Ready ### AI Disclosure - Tool: Claude Code (Claude Opus 5.5) - Generated: the code, the tests, and this description - Human review: not stated - Prompts: The author first asked for a generic connector SPI to mask a connector's secret catalog properties instead of adding the Lance keys to fe-core's list. Then, in this PR: let the surface express prefix rules such as Fluss's, mask the union of the engine's and the connectors' keys, wire every connector, keep fe-core's existing entries as the floor, mask whatever is marked `sensitive` but stop marking keytab paths, and fix the unmasked ALTER CATALOG audit text on master only. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…udit text ### Background SHOW CREATE CATALOG, SHOW CATALOG, the `catalogs()` table function and the audit text of CREATE CATALOG replace a property value with `*XXX` when `DatasourcePrintableMap.isSensitiveKey` matches its key. Until now the keys came from a list in fe-core and from the keys filesystem plugins report at startup. A connector plugin marks its secret properties `sensitive = true`, but that mark only masks the connector's own log lines. A connector tells the engine about its security-relevant properties through `ConnectorProvider#securitySurface()`. ### What problem does this PR solve? Issue Number: None Related PR: apache#69588 (added the connector security surface this extends), apache#45164 (introduced the unmasked ALTER CATALOG audit text), apache#27115 (masked it for the statement apache#45164 replaced), apache#59502 (added `iceberg.jdbc.password`), apache#54523 (added the Paimon REST DLF keys), apache#65730 (branch-4.1's Lance catalog, whose REST secrets the Lance port will declare on this surface) PR Type: Bugfix Problem Summary: Catalog secrets that only a connector knows are on no masking list, so SHOW CREATE CATALOG and the other renderings print them in clear: `iceberg.jdbc.password`, `paimon.jdbc.password`, the Paimon REST DLF key pair, `mc.access_key`, and credentials passed through under `trino.` or `adbc.`. Separately, `ALTER CATALOG ... SET PROPERTIES` is written to the audit log unmasked, whatever the key. Each connector now declares its secrets on its security surface, taken from its `sensitive` marks, and the surface can also declare a namespace of secret keys for options passed through unread; Fluss's lake options were hard-coded in fe-core for that reason. The engine masks the union, with fe-core's own list kept as the floor. ALTER CATALOG is masked like CREATE CATALOG. ### Details - **Change map:** 42 files, +1035 −76 over two commits: production code +376 −48, tests +645 −24, the connector README +13 −3, the plugin API version in `fe/fe-connector/pom.xml`. The first commit adds secret keys to the surface (reviewed alone before). The second does the rest: 1. Key namespaces on the SPI: `withSensitiveKeyPrefix` and `SensitiveKeyPrefix.covers`, which holds the matching rule; a collection form of `withSensitiveKeys` (`ConnectorSecuritySurface`, +130). 2. Engine: `isSensitiveKey` matches registered namespaces, the Fluss rule becomes one of them; `ConnectorPluginManager` registers them and reads every surface before it publishes a provider (+70). 3. Connectors: every provider declares its secrets; `MetaStoreProviders.sensitivePropertyKeys()` gives the union of a plugin's metastore backends; `IcebergJdbcMetaStoreProvider` reports its keys like its siblings; the keytab paths lose their `sensitive` mark (+140). 4. ALTER CATALOG audit masking (+16). - **Frequency:** Always. Create or alter a catalog that sets one of the keys above, then run SHOW CREATE CATALOG, SHOW CATALOG `<name>` or `select * from catalogs()`, or read the audit log after an ALTER CATALOG ... SET PROPERTIES. - **Root cause:** `isSensitiveKey` consulted only fe-core's list and the filesystem providers' keys. A connector's `sensitive` marks fed only `toMaskedString`; `MetaStoreProvider.sensitivePropertyKeys()` existed for this, but nothing called it, and the Iceberg JDBC backend did not implement it. For ALTER CATALOG, `AlterCatalogPropertiesCommand` does not implement `NeedAuditEncryption` and `LogicalPlanBuilderForEncryption` has no `visitAlterCatalogProperties`, so `AuditLogHelper` records the original text; the statement it replaced in apache#45164 was masked by apache#27115. - **Why existing tests missed it:** Unit tests: `DatasourcePrintableMapTest` checks fe-core's own keys, the provider surface tests checked only the SSRF and driver_url keys, and `EncryptSQLTest` and `RepositoryAuditEncryptionTest` cover CREATE CATALOG, repositories and resources but not ALTER CATALOG. Regression: `audit/test_external_catalog_credential_masking` creates only Iceberg REST catalogs, whose keys are on fe-core's list, and never alters one. - **Fix:** The engine must not name a connector's properties, so the connectors declare their secrets, from the same `sensitive` marks that mask their logs; jdbc and es declare both spellings their legacy prefix allows, and trino and adbc declare the namespace they pass through, a key there being a secret when its rest names `key`, `secret`, `password`, `token` or `credential` (also `authorization` for ADBC). fe-core keeps the connector keys it lists, so a catalog whose plugin is not loaded masks what it masked before. A provider whose `securitySurface()` throws at startup is skipped, as a filesystem provider is, instead of stopping FE. - **Other paths and branches:** Fixed here: every rendering above and FE's statement logging, which share `isSensitiveKey` and `NeedAuditEncryption`. Not covered, since a key name cannot express them safely: raw Iceberg SDK keys copied through (`token`, `credential`), Paimon options re-keyed from `paimon.*`, Hadoop `fs.*` keys, and secrets inside a URL. The ALTER CATALOG gap is on branch-4.0, 4.1 and 4.2 (from apache#45164); branch-3.1 still uses the masked statement. branch-4.1 and 4.2 also print the connector keys above in clear; without the connector SPI their fix differs and is tracked separately. - **Behavior change:** The namespaces also mask non-secrets whose names carry those words, such as `trino.hive.s3.aws-access-key` or a keystore path. Keytab paths, which no release masks, are no longer masked in connector log lines: marked `sensitive`, `hadoop.kerberos.keytab` would be masked in every storage vault and resource. ### Testing All runs were local (macOS), on master `f5c993f2c94` plus this change: - Regression `audit/test_external_catalog_credential_masking`, extended with an Iceberg JDBC catalog: SHOW CREATE CATALOG masks `iceberg.jdbc.password`, and the audit texts of its CREATE CATALOG and of an ALTER CATALOG that sets the password and `s3.secret_key` hold only `*XXX`. Against the local cluster's FE without this change it fails at the first new check, SHOW CREATE CATALOG printing the password; with a FE built from this change it passes. - fe-connector-spi: all 160 tests, with the refreshed surface baseline (+4 lines); the metastore modules: all tests; ten connector modules: 29 classes, 511 tests, including each connector's surface test, which checks real key names. - fe-core: 26 classes, 341 tests, including `ConnectorPluginManagerTest`, `DatasourcePrintableMapTest`, `EncryptSQLTest` and the audit and plugin gate tests; 14 of them again after the last change to registration. - Twenty mutations, each caught by its test: for example, reverting either half of the ALTER CATALOG fix (`EncryptSQLTest` sees the statement in clear), matching a marker anywhere in the key, an empty metastore union, or re-marking a keytab. ### Notes for Reviewers - `SensitiveKeyPrefix.covers` lives on the SPI so that a connector's test can check its declaration against real key names and the engine applies the same rule; the Fluss floor in fe-core uses it too. - The entries both fe-core and a connector declare are deliberate: the floor is frozen, as the comment in `DatasourcePrintableMap` says. - The plugin API stays at 31.0, the first commit's bump. Hudi declares nothing: it owns no catalog properties. ### Release note SHOW CREATE CATALOG, SHOW CATALOG, the `catalogs()` table function and the audit log now mask `iceberg.jdbc.password`, `paimon.jdbc.password`, `paimon.rest.dlf.access-key-id`, `paimon.rest.dlf.access-key-secret`, `mc.access_key`, and the `trino.*` and `adbc.*` properties whose names carry `key`, `secret`, `password`, `token` or `credential` (`authorization` too for `adbc.*`). ALTER CATALOG ... SET PROPERTIES statements are masked in the audit log like CREATE CATALOG. ### Check List (For Author) - Behavior changed: Yes (see Details) - Does this need documentation: No - Pre-submission status: Ready ### AI Disclosure - Tool: Claude Code (Claude Opus 5.5) - Generated: the code, the tests, and this description - Human review: not stated - Prompts: The author first asked for a generic connector SPI to mask a connector's secret catalog properties instead of adding the Lance keys to fe-core's list. Then, in this PR: let the surface express prefix rules such as Fluss's, mask the union of the engine's and the connectors' keys, wire every connector, keep fe-core's existing entries as the floor, mask whatever is marked `sensitive` but stop marking keytab paths, and fix the unmasked ALTER CATALOG audit text on master only. Co-Authored-By: Claude Opus 5.5 <[email protected]>
What problem does this PR solve?
Issue Number: close #xxx
Related PR: #xxx
Problem Summary:
Currently, Doris supports multiple Iceberg catalog types (HMS, REST, Hadoop, Glue, DLF, S3Tables) but lacks support for JDBC Catalog. This PR adds support for Iceberg JDBC Catalog, which allows users to store Iceberg metadata in relational databases like PostgreSQL, MySQL, and SQLite.
Key Changes:
IcebergJdbcMetaStorePropertiesclass to handle JDBC catalog configurationsIcebergJdbcExternalCatalogclass for JDBC catalog operationsBenefits:
Release note
Features
Check List (For Author)
Manual Test Steps:
Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)