Skip to content

[improvement](fe) Upgrade iceberg to 1.12.0 - #69031

Merged
morningman merged 6 commits into
apache:masterfrom
laskoviymishka:iceberg-1.12
Oct 15, 2026
Merged

morningman merged 6 commits into
apache:masterfrom
laskoviymishka:iceberg-1.12

Conversation

@laskoviymishka

@laskoviymishka laskoviymishka commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Upgrade the Iceberg Java SDK from 1.11.0 to 1.12.0. 1.12.0. This change only upgrades the dependency and adapts Doris to it.

  • Bump iceberg.version 1.11.0 -> 1.12.0, and avro.version 1.12.1 -> 1.12.2 to stay consistent with what iceberg 1.12.0 is built against (the pom requires the two to move together).
  • Bump the explicit caffeine pin in fe-connector-iceberg 2.9.3 -> 3.2.4. Iceberg 1.12.0 moved to caffeine 3. The pin is a direct dependency, so it wins Maven mediation; leaving it at 2.9.3 would package an older caffeine into the iceberg plugin than iceberg-core is built against.
  • Re-vendor org.apache.iceberg.DeleteFileIndex from 1.12.0 and re-apply the Doris changes (public class/builder methods, schemasById comment, equality-field-id sets). The vendored class shadows the SDK class in the same package, and 1.12.0 changed it (an extra specsById constructor argument and delete/data file partition-match validation), so keeping the 1.11.0 copy would break the SDK's own callers at runtime. Since Doris passes specsById to the builder, the cached scan planning path now also rejects delete files whose partition spec or tuple does not match the data file, the same as upstream iceberg.
  • Pass table.specs() to ManifestFiles.read in IcebergManifestCache. Iceberg 1.12.0 removed the deprecated read(ManifestFile, FileIO) overload, which read the partition specs from the manifest file's own metadata (only possible for Avro manifests). This matches the delete manifest path next to it (readDeleteManifest(..., table.specs())) and IcebergRemoveOrphanFilesAction.
  • Keep the AWS SDK at 2.29.52 and default iceberg-aws's HTTP client to urlconnection. In 1.12.0, iceberg-aws's default http-client.type (apache) builds an Apache5HttpClient from software.amazon.awssdk:apache5-client, which first shipped in AWS SDK 2.32. Doris pins 2.29.52 on purpose ([fix](S3)Downgrade the AWS SDK version to avoid impacting other S3-compatible services. #58566: newer SDKs add default S3 integrity checksums that break S3-compatible services), so with the default every S3FileIO, Glue and STS client iceberg builds failed with NoClassDefFoundError: software/amazon/awssdk/http/apache5/Apache5HttpClient$Builder. IcebergCatalogFactory.buildBaseCatalogProperties, the base of every catalog flavor, now sets http-client.type=urlconnection unless the catalog sets it. S3FileIO keeps the setting when it is serialized, so the BE iceberg metadata scanner, which rebuilds the FileIO from it, uses the same client; url-connection-client is added to that scanner, which only bundled apache-client and netty-nio-client. An explicit http-client.type=apache is rejected at CREATE/ALTER CATALOG instead of failing on the first S3 or Glue call.

SchemaAwareDataTableScan (the other vendored class) needs no change: DataTableScan, BaseTableScan, SnapshotScan and TableScanContext are identical between 1.11.0 and 1.12.0.

Release note

Upgrade the Iceberg Java SDK to 1.12.0. Iceberg's AWS clients (S3FileIO, Glue, STS) now use the URLConnection HTTP client by default, and the http-client.type=apache catalog property is no longer accepted. Iceberg 1.12.0 no longer reads the S3 remote-signing properties s3.signer.uri and s3.signer.endpoint and no longer defaults the signer endpoint to v1/aws/s3/sign, so an Iceberg REST server that enables S3 remote signing must send signer.uri / signer.endpoint or serve the table-scoped sign endpoint. Iceberg system tables ($snapshots, $files, ...) cannot be queried while FE and BE are on different Iceberg versions (1.11 and 1.12), e.g. during a rolling upgrade; they work again once every node is upgraded.

Check List (For Author)

  • Test: Unit Test
    • Added IcebergCatalogFactoryTest#buildBaseDefaultsIcebergAwsHttpClientToUrlConnection (builds a real S3 client builder with the default) and #buildBaseKeepsAnExplicitHttpClientType, and IcebergCatalogPropertiesTest#createTimeRulesRejectTheApacheHttpClientType; IcebergCatalogOptionsSnapshotTest snapshots now include the default.
    • build.sh --fe passes. Ran every iceberg FE unit test with run-fe-ut.sh (fe-connector-iceberg, fe-connector-metastore-iceberg, be-java-extensions/iceberg-metadata-scanner): 1630 tests, 0 failures, 5 skipped.
    • Iceberg regression suites not run.
  • Behavior changed: Yes.
    • Iceberg's AWS clients use the URLConnection HTTP client by default, so http-client.apache.* properties no longer apply, and http-client.type=apache is rejected at CREATE/ALTER CATALOG.
    • Iceberg scans whose delete files have a partition spec or partition tuple that does not match the data file now fail with a ValidationException (iceberg 1.12.0 behavior) instead of applying the deletes.
    • S3 remote signing: iceberg 1.12.0 no longer reads s3.signer.uri / s3.signer.endpoint and no longer defaults the signer endpoint to v1/aws/s3/sign. A REST catalog whose server turns on remote signing but sends only those legacy keys, or relies on that default, fails to read manifests. No compatibility shim is added: Doris does not use remote signing to read data (BE uses static or vended credentials), and signer.uri / signer.endpoint are deprecated in 1.12.0 and scheduled for removal in 1.13.0.
    • Iceberg system tables cannot be queried while FE and BE are on different Iceberg versions (1.11 and 1.12), e.g. during a rolling upgrade: iceberg 1.12.0 changed the serialized form of BaseFile and PartitionData, which system table tasks carry. BE reports the version mismatch instead of a bare InvalidClassException. Normal data scans are not affected.
  • Does this need documentation: No

What problem does this PR solve?

Issue Number: related #68916

Problem Summary:

Release note

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Upgrade the Iceberg Java SDK from 1.11.0 to 1.12.0.
1.12.0 brings the client side of REST catalog labels (`Labels`,
`SupportsLabels`, labels on `LoadTableResponse`, see apache/iceberg#15750,
apache#18045, apache#18046), which Doris needs before it can expose catalog-provided
labels for iceberg tables. This change only upgrades the dependency and
adapts Doris to it.

- Bump `iceberg.version` 1.11.0 -> 1.12.0, and `avro.version`
  1.12.1 -> 1.12.2 to stay consistent with what iceberg 1.12.0 is built
  against (the pom requires the two to move together).
- Bump the explicit caffeine pin in fe-connector-iceberg 2.9.3 -> 3.2.4.
  Iceberg 1.12.0 moved to caffeine 3. The pin is a direct dependency, so
  it wins Maven mediation; leaving it at 2.9.3 would package an older
  caffeine into the iceberg plugin than iceberg-core is built against.
- Re-vendor `org.apache.iceberg.DeleteFileIndex` from 1.12.0 and re-apply
  the Doris changes (public class/builder methods, schemasById comment,
  equality-field-id sets). The vendored class shadows the SDK class in
  the same package, and 1.12.0 changed it (an extra `specsById` constructor
  argument and delete/data file partition-match validation), so keeping
  the 1.11.0 copy would break the SDK's own callers at runtime.
  Since Doris passes `specsById` to the builder, the cached scan planning
  path now also rejects delete files whose partition spec or tuple does
  not match the data file, the same as upstream iceberg.
- Pass `table.specs()` to `ManifestFiles.read` in `IcebergManifestCache`.
  Iceberg 1.12.0 removed the deprecated `read(ManifestFile, FileIO)`
  overload, which read the partition specs from the manifest file's own
  metadata (only possible for Avro manifests). This matches the delete
  manifest path next to it (`readDeleteManifest(..., table.specs())`)
  and `IcebergRemoveOrphanFilesAction`.
- Keep the AWS SDK at 2.29.52 and default iceberg-aws's HTTP client to
  `urlconnection`. In 1.12.0, iceberg-aws's default `http-client.type`
  (`apache`) builds an `Apache5HttpClient` from
  `software.amazon.awssdk:apache5-client`, which first shipped in AWS SDK
  2.32. Doris pins 2.29.52 on purpose (apache#58566: newer SDKs add default S3
  integrity checksums that break S3-compatible services), so with the
  default every S3FileIO, Glue and STS client iceberg builds failed with
  `NoClassDefFoundError: software/amazon/awssdk/http/apache5/Apache5HttpClient$Builder`.
  `IcebergCatalogFactory.buildBaseCatalogProperties`, the base of every
  catalog flavor, now sets `http-client.type=urlconnection` unless the
  catalog sets it. S3FileIO keeps the setting when it is serialized, so
  the BE iceberg metadata scanner, which rebuilds the FileIO from it,
  uses the same client; `url-connection-client` is added to that scanner,
  which only bundled `apache-client` and `netty-nio-client`. An explicit
  `http-client.type=apache` is rejected at CREATE/ALTER CATALOG instead of
  failing on the first S3 or Glue call.

- Report the mixed-version case clearly. FE sends iceberg system-table
  splits to the BE as Java-serialized iceberg objects, and iceberg 1.12.0
  changed the serialized form of classes every split carries (`BaseFile`,
  `PartitionData`, their anonymous inner classes; 24 serializable classes
  changed `serialVersionUID`). Unlike 1.11.0, where only `Schema` changed
  and is shimmed, this cannot be bridged by remapping UIDs, so while FE and
  BE run different iceberg versions (a rolling upgrade) iceberg system
  tables cannot be read. `IcebergSerializationCompat` now turns the bare
  `InvalidClassException` / `ClassNotFoundException` into an error naming
  the cause and the BE's iceberg version, and the shim comments no longer
  claim a shared wire across versions.

`SchemaAwareDataTableScan` (the other vendored class) needs no change:
`DataTableScan`, `BaseTableScan`, `SnapshotScan` and `TableScanContext`
are identical between 1.11.0 and 1.12.0.

### Release note

Upgrade the Iceberg Java SDK to 1.12.0. Iceberg's AWS clients (S3FileIO,
Glue, STS) now use the URLConnection HTTP client by default, and the
`http-client.type=apache` catalog property is no longer accepted. During a
rolling upgrade from a release on Iceberg 1.11, Iceberg system tables
(`tbl$snapshots`, `tbl$files`, ...) are unavailable until FE and BE are
both upgraded.

### Check List (For Author)

- Test: Unit Test
    - Added IcebergCatalogFactoryTest#buildBaseDefaultsIcebergAwsHttpClientToUrlConnection
      (builds a real S3 client builder with the default) and
      #buildBaseKeepsAnExplicitHttpClientType, and
      IcebergCatalogPropertiesTest#createTimeRulesRejectTheApacheHttpClientType;
      IcebergCatalogOptionsSnapshotTest snapshots now include the default.
    - Added IcebergSerializationCompatTest#reportsATaskFromAnotherIcebergVersion
      (a DataFile carrying Iceberg 1.11's BaseFile UID) and
      #reportsAClassThisIcebergDoesNotHave.
    - Verified the mixed-version break outside the build: a DataFile written
      with iceberg 1.11.0 cannot be read with 1.12.0 and vice versa, even
      after rewriting every changed class UID in the stream.
    - `build.sh --fe` passes. Ran every iceberg FE unit test with
      run-fe-ut.sh (fe-connector-iceberg, fe-connector-metastore-iceberg,
      be-java-extensions/iceberg-metadata-scanner): 1650 tests, 0 failures,
      5 skipped.
    - Iceberg regression suites not run.
- Behavior changed: Yes.
    - Iceberg's AWS clients use the URLConnection HTTP client by default,
      so `http-client.apache.*` properties no longer apply, and
      `http-client.type=apache` is rejected at CREATE/ALTER CATALOG.
    - Iceberg scans whose delete files have a partition spec or partition
      tuple that does not match the data file now fail with a
      ValidationException (iceberg 1.12.0 behavior) instead of applying
      the deletes.
    - While FE and BE run different iceberg versions (rolling upgrade from
      iceberg 1.11), iceberg system tables fail with an explicit
      "different Iceberg version" error until both sides are upgraded.
- Does this need documentation: No
@morningman

Copy link
Copy Markdown
Contributor

1. [Must fix] Give the storage connectivity probe the same HTTP client default

Why. The default http-client.type=urlconnection is injected only in IcebergCatalogFactory.buildBaseCatalogProperties. IcebergConnector.probeStorage does not go through that method. It builds its own map in buildStorageProbeProperties (IcebergConnector.java:493), with only s3.* and client.region, and then loads an S3FileIO from it (:467). Under iceberg 1.12.0 that S3FileIO falls back to the apache client type, which is Apache5HttpClient, so building the client throws NoClassDefFoundError: software/amazon/awssdk/http/apache5/Apache5HttpClient$Builder. That is an Error. It is not caught by catch (Exception e) (:471), so it never becomes a "connectivity test failed" message. CREATE CATALOG fails with Unexpected exception: software/amazon/awssdk/http/apache5/... whether the credentials are right or wrong.

The failure was reproduced with iceberg 1.12.0 and AWS SDK 2.29.52, using exactly the probe's properties against a closed local port. Without the key the call throws NoClassDefFoundError. With http-client.type=urlconnection it fails normally with SdkClientException: Connection refused. regression-test/suites/external_table_p0/test_connection/test_iceberg_rest_minio_connectivity.groovy covers this path and would fail in both of its probe cases.

Fix. Move the default into one helper and call it from both places. A better version also copies the catalog's http-client.* keys into the probe map, so the probe uses the same transport and proxy settings as the catalog.

// IcebergCatalogFactory
/**
 * iceberg-aws's default "apache" client is Apache5HttpClient since iceberg 1.12, which needs AWS SDK >= 2.32;
 * Doris pins 2.29.x (#58566). Every map that ends up building an iceberg AWS client must go through this.
 */
static void applyDefaultAwsHttpClient(Map<String, String> opts) {
    opts.putIfAbsent(HttpClientProperties.CLIENT_TYPE, HttpClientProperties.CLIENT_TYPE_URLCONNECTION);
}
 // IcebergConnector.buildStorageProbeProperties
         ioProps.put("s3.remote-signing-enabled", "false");
+        IcebergCatalogFactory.applyDefaultAwsHttpClient(ioProps);

Add a test written the same way as the PR's own factory test, so the probe map is checked against the shipped SDK:

@Test
public void storageProbePropertiesBuildAnS3ClientOnTheShippedSdk() {
    Map<String, String> ioProps = IcebergConnector.buildStorageProbeProperties(
            IcebergCatalogProperties.TYPE_REST,
            new FakeS3CompatibleStorageProperties("S3").endpoint("http://127.0.0.1:1")
                    .region("us-east-1").accessKey("ak").secretKey("sk"));
    // MUTATION: drop the default -> "apache" -> NoClassDefFoundError -> red.
    Assertions.assertDoesNotThrow(
            () -> new HttpClientProperties(ioProps).applyHttpClientConfigurations(S3Client.builder()));
}

After the fix, run the iceberg cases under external_table_p0/test_connection.

…nnectivity probe

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69031

Problem Summary: The iceberg 1.12.0 upgrade defaults iceberg-aws's HTTP
client to `urlconnection` in `IcebergCatalogFactory.buildBaseCatalogProperties`,
because iceberg-aws's default `apache` type is `Apache5HttpClient` since
1.12.0 and needs an AWS SDK newer than the 2.29.52 Doris pins (apache#58566).

The CREATE CATALOG storage connectivity probe does not go through that
method. `IcebergConnector.buildStorageProbeProperties` builds its own map
(only `s3.*` and `client.region`) and `probeStorage` loads an `S3FileIO`
from it, so the probe fell back to `apache` and building the S3 client
threw `NoClassDefFoundError: software/amazon/awssdk/http/apache5/Apache5HttpClient$Builder`.
That is an `Error`, not caught by the probe's `catch (Exception e)`, so it
never became a "connectivity test failed" result: CREATE CATALOG with
static S3 credentials failed with an unexpected exception whether the
credentials were right or wrong.

- Move the default into `IcebergCatalogFactory.applyDefaultAwsHttpClient`
  and apply it in both `buildBaseCatalogProperties` and
  `buildStorageProbeProperties`.
- Copy the catalog's `http-client.*` settings (client type, proxy,
  timeouts) into the probe map, so the probe reaches storage the same way
  the catalog does; `s3.*` still comes only from the bound storage.

The other places the connector builds AWS clients do not need it: every
catalog flavor (DLF included) goes through `buildBaseCatalogProperties`;
the s3tables control-plane client uses the s3tables library's own
`HttpClientProperties`, whose `apache` type is the v4 `ApacheHttpClient`
shipped with 2.29.52; DLF's own `S3Client` sets `UrlConnectionHttpClient`
explicitly; the STS assume-role client is a plain AWS SDK builder.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Added IcebergConnectorTestConnectionTest#storageProbePropertiesBuildAnS3ClientOnTheShippedSdk
      (builds a real S3 client builder from the probe map on the shipped
      SDK) and #storageProbeUsesTheCatalogHttpClientSettings.
    - `build.sh --fe` passes. Ran every iceberg FE unit test with
      run-fe-ut.sh (fe-connector-iceberg, fe-connector-metastore-iceberg,
      be-java-extensions/iceberg-metadata-scanner): 1652 tests, 0 failures,
      5 skipped.
    - The external_table_p0/test_connection regression cases were not run
      (no docker regression environment available locally).
- Behavior changed: No (fixes a regression of the iceberg 1.12.0 upgrade
  in apache#69031 before it is released)
- Does this need documentation: No

Co-authored-by: Isaac <no-reply@databricks.com>
@morningman

Copy link
Copy Markdown
Contributor

run buildall

@morningman

Copy link
Copy Markdown
Contributor

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of commit 968a0f7: one P1 and two P2 findings. The shared Avro bump breaks Hudi V2 commit readers; an empty HTTP-client type selects the unsupported Apache5 transport; current-spec manifest decoding breaks cached historical streaming scans after partition type promotion. All three verified findings are inline. No prior inline threads or existing blocking findings were present. No additional user focus was supplied.

Reviewed all 15 changed files, their callers and downstream consumers, and primary released Iceberg/Avro/Hudi/AWS sources. Three reviewers covered catalogs/dependencies, scans/task serialization, and a separate AWS runtime risk review. Static-only: no builds, tests, or source changes were performed; author-reported test results were not treated as reviewer execution evidence.

Critical checkpoint conclusions:

  • Goal and proof: the 1.12 dependency/API adaptations are present, but the three inline regressions prevent full compatibility. Added tests do not cover their concrete triggers.
  • Scope and reuse: adaptations are focused and reuse the shared factory; the global Avro pin also affects Hudi and needs consumer-specific treatment.
  • Concurrency: local option maps introduce no shared mutation; lazy scan/cache workers and comparator loading preserve existing synchronization and TCCL boundaries. No new lock-order defect found.
  • Lifecycle and initialization: readers close and cached file copies survive iterator reuse; comparator caches are scan-owned. Hudi class-based datum-reader initialization fails as described in the P1 finding.
  • Configuration: existing http-client.type changes default/allowed values; CREATE and ALTER validate, and ALTER reconstructs the connector. Empty input is missed. Replay retains statement-only validation bypass.
  • Compatibility: vendored DeleteFileIndex matches the released 1.12 ABI plus Doris public/equality-ID extensions; Schema's serialized fields remain unchanged. Global Avro restrictions and historical partition typing produce the inline findings.
  • Thrift/protobuf: no definition or field-ID changes.
  • Parallel paths: checked all seven catalog flavors, CREATE probe and lazy catalog, direct DLF/S3Tables clients, SDK/cache and synchronous/streaming/count scans, JNI system tables and native position-deletes. The cache's eager fallback masks the historical error in synchronous planning but cannot catch lazy streaming evaluation.
  • Conditions and errors: upstream spec/tuple validation has concrete corruption failure paths and useful file context; unsupported literal apache has an actionable error. Empty default handling is incomplete.
  • Test coverage: JUnit cases cover property defaults, literal apache rejection, probe propagation and synthetic serialization failures. Missing cases include actual Hudi V2 commit decoding, empty transport, and streamed historical INT-to-LONG identity partitions. Runtime/e2e compatibility was not executed.
  • Test results: no regression goldens changed. The old serialized fixture has a null metadata file and cannot demonstrate real mixed-version task compatibility.
  • Observability: existing probe/cache/streaming diagnostics retain catalog/table context and causes; the new serialization error identifies version skew. No additional metric requirement identified.
  • Persistence and transactions: no journal format, snapshot commit or native transaction changes; existing snapshot selection still fences data/delete enumeration. Persisted transport values require the declared migration.
  • Writes and atomicity: no new write/commit/crash-recovery path; delete-index changes validate association before use and do not mutate data.
  • FE-to-BE variables: no new thrift variable; existing serialized FileIO properties carry the transport, and the scanner now packages URLConnection. Native data/position-deletes payloads stay on the existing path.
  • Performance and memory: option processing is linear in property count outside scan loops; comparators are cached per spec and validation is proportional to attached deletes. No new BE allocator/tracker path. Historical synchronous fallback can reread manifests.
  • Other concerns: no additional independently substantiated issue after rechecks. Explicit Apache selection (including forced REST overrides) and Apache-specific timeout keys are intentional declared migration limits, rather than additional inline bugs.

Declared upgrade limits remain: many real Java-serialized system-table tasks, including $snapshots/$files, cannot cross Iceberg 1.11/1.12 FE/BE versions; normal native data scans and native $position_deletes avoid that wire. Existing explicit apache settings must become urlconnection, with server-side migration when REST overrides force apache; Apache timeout keys must become URLConnection timeout keys. These limits were checked statically and are not claims of executed rolling-upgrade coverage.

Convergence: converged after 2 rounds. All three assigned reviewers returned NO_NEW_VALUABLE_FINDINGS in round 2; all changed-file coverage and every candidate/risk disposition are complete. No unresolved source question or uncovered source scope remains. The execution limits and declared migration limits above remain explicit.

Review converged after 2 round(s).

Comment thread fe/pom.xml Resolved
laskoviymishka and others added 3 commits October 13, 2026 20:32
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69031

Problem Summary: The iceberg 1.12.0 upgrade also raised the global
`avro.version` from 1.12.1 to 1.12.2, the version iceberg 1.12.0 is built
against. `avro.version` is shared: it also upgrades `fe-connector-hudi`
and `be-java-extensions/hadoop-hudi-scanner`.

Avro 1.12.2 forbids `SpecificDatumReader` and `java-class` schema
attributes from instantiating classes outside
`org.apache.avro.SERIALIZABLE_CLASSES` / `SERIALIZABLE_PACKAGES`
(AVRO-4189), and throws `SecurityException: Forbidden ...` by default.
Hudi reads timeline metadata exactly that way: for a Hudi 1.0 table with a
completed non-legacy V2 commit, a COW incremental query reaches
`CommitMetadataSerDeV2` -> `TimelineMetadataUtils.deserializeAvroMetadata`
-> `new SpecificDatumReader<>(HoodieCommitMetadata.class)`, which avro
1.12.2 rejects, so the query fails on a valid table.

Iceberg 1.12.0 does not need 1.12.2: every avro member referenced by the
iceberg-api/core/common/aws 1.12.0 bytecode resolves against avro 1.12.1
(linkage-checked with javap, 182 members, none missing), and master
already runs iceberg on avro 1.12.1. Keep `avro.version` at 1.12.1 and
document why it intentionally differs from iceberg's.

### Release note

None

### Check List (For Author)

- Test: Manual test + Unit Test
    - `build.sh --fe` with the Maven build cache disabled passes, and every
      module packages avro-1.12.1: fe/lib, the hive/hudi/iceberg/paimon
      connector plugins and the BE java extensions (hadoop-hudi-scanner,
      iceberg-metadata-scanner, paimon-scanner, hadoop-deps).
    - Ran every iceberg and hudi FE unit test with run-fe-ut.sh: 1933 tests,
      0 failures, 5 skipped.
    - A Hudi V2 commit-metadata read (COW incremental query) was not run
      locally.
- Behavior changed: No (restores master's avro version)
- Does this need documentation: No

Co-authored-by: Isaac <no-reply@databricks.com>
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69031

Problem Summary: The iceberg 1.12.0 upgrade defaults iceberg-aws's HTTP
client to `urlconnection` (`IcebergCatalogFactory.applyDefaultAwsHttpClient`)
because iceberg-aws's own default, `apache`, is `Apache5HttpClient` since
1.12.0 and needs an AWS SDK newer than the 2.29.52 Doris pins. The default
was applied with `putIfAbsent`, so a catalog with `http-client.type=""`
(set at CREATE, or by an ALTER that clears it) kept the empty value. It
passes the CREATE/ALTER check that rejects `apache`, and iceberg-aws's
`HttpClientProperties` then maps the empty type back to `apache`, so the
first S3/Glue call or the CREATE storage probe failed with
`NoClassDefFoundError: software/amazon/awssdk/http/apache5/Apache5HttpClient$Builder`.
Before the upgrade the same empty value selected the working Apache 4
client.

Treat a blank `http-client.type` as unset in `applyDefaultAwsHttpClient`,
which both the catalog properties and the storage probe properties go
through.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Added IcebergCatalogFactoryTest#buildBaseTreatsABlankHttpClientTypeAsUnset
      and IcebergConnectorTestConnectionTest#storageProbeTreatsABlankCatalogHttpClientTypeAsUnset;
      both build a real S3 client builder on the shipped AWS SDK.
    - `build.sh --fe` passes. Ran every iceberg and hudi FE unit test with
      run-fe-ut.sh: 1933 tests, 0 failures, 5 skipped.
- Behavior changed: No (fixes a regression of the iceberg 1.12.0 upgrade
  in apache#69031 before it is released)
- Does this need documentation: No

Co-authored-by: Isaac <no-reply@databricks.com>
…pecs

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69031

Problem Summary: iceberg 1.12.0 removed the deprecated
`ManifestFiles.read(ManifestFile, FileIO)`, which read the partition spec
from the manifest file's own metadata. The upgrade replaced it in
`IcebergManifestCache` with `read(manifest, io, table.specs())`, which
binds every manifest to the CURRENT schema's partition types.

The cache-backed planner evaluates residuals and builds the delete index
with the scan's specs (`SchemaAwareDataTableScan.specsFor(scan)`), bound to
the scan's schema. After an identity partition column is promoted (for
example `p INT` -> `BIGINT`), a scan pinned to a snapshot before the
promotion binds its residual to INT while the cached partition values are
`Long`, so `WHERE p = 1` on the old snapshot with the manifest cache and
batch streaming failed with
`IllegalArgumentException: Wrong class, expected java.lang.Integer, but was java.lang.Long`
(the residual is evaluated after the streaming fallback, so it is not
retried). Going back to the manifest's own spec does not help: the cache is
keyed by manifest path only, so a current scan then reads the old INT
values and fails the other way (`expected java.lang.Long, but was
java.lang.Integer`), depending on which scan filled the cache first.

- Read data and delete manifests in `IcebergManifestCache` with the scan's
  spec map, the same one its residuals and delete index use, so partition
  values always have the types the scan evaluates.
- Add the bound partition type of the manifest's spec to
  `IcebergManifestEntryKey`, so scans whose schemas bind a manifest to
  different partition types get separate cached copies; scans with the same
  binding still share one entry, as before.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Added IcebergScanPlanProviderTest#cachedStreamingScansKeepPartitionTypesAcrossIntToBigintPromotion:
      a v2 table identity-partitioned by p INT with a position delete,
      p promoted to BIGINT, then a historical scan (p = 1 as INT) and a
      current scan (p = 1 as BIGINT) streamed through one manifest cache, in
      both warm-up orders. It fails without this fix with the reported
      "expected java.lang.Integer, but was java.lang.Long", and also fails
      (the other way round) if manifests are decoded with their own spec.
    - Added IcebergManifestEntryKeyTest#differentBoundPartitionTypeAreNotEqual.
    - `build.sh --fe` (Maven build cache disabled) passes. Ran every iceberg
      and hudi FE unit test with run-fe-ut.sh: 1933 tests, 0 failures,
      5 skipped.
- Behavior changed: No (fixes a regression of the iceberg 1.12.0 upgrade
  in apache#69031 before it is released)
- Does this need documentation: No

Co-authored-by: Isaac <no-reply@databricks.com>
@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29061 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 98679abb2b68d36033e4e8fe8e10078168beb193, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17577	5568	5514	5514
q2	2062	310	300	300
q3	10220	1384	814	814
q4	4683	473	356	356
q5	7449	805	542	542
q6	193	187	152	152
q7	768	797	604	604
q8	9266	1328	1115	1115
q9	5764	4452	4440	4440
q10	6815	1295	1027	1027
q11	434	251	238	238
q12	628	405	286	286
q13	18060	3035	2373	2373
q14	271	271	250	250
q15	q16	734	726	670	670
q17	1174	768	595	595
q18	7133	6235	6151	6151
q19	1103	957	597	597
q20	380	345	223	223
q21	5361	2525	2574	2525
q22	410	357	289	289
Total cold run time: 100485 ms
Total hot run time: 29061 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6494	6465	6474	6465
q2	717	598	556	556
q3	5610	5774	5330	5330
q4	2045	2173	1566	1566
q5	5797	5722	5527	5527
q6	252	192	152	152
q7	2296	2060	1847	1847
q8	3130	2713	2803	2713
q9	8227	8023	7699	7699
q10	3663	3580	3228	3228
q11	593	403	383	383
q12	670	696	503	503
q13	2733	3090	2380	2380
q14	282	293	252	252
q15	q16	664	682	601	601
q17	7744	6986	6845	6845
q18	13177	12240	13047	12240
q19	920	787	784	784
q20	2177	2166	1949	1949
q21	5887	4743	4774	4743
q22	486	474	416	416
Total cold run time: 73564 ms
Total hot run time: 66179 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152569 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 98679abb2b68d36033e4e8fe8e10078168beb193, data reload: false

query5	4308	617	500	500
query6	425	218	208	208
query7	4808	454	228	228
query8	318	185	170	170
query9	8784	4030	4020	4020
query10	477	316	258	258
query11	5962	3432	3155	3155
query12	147	91	85	85
query13	1260	469	339	339
query14	6573	4816	4508	4508
query14_1	4236	4278	4286	4278
query15	213	200	180	180
query16	939	438	414	414
query17	872	685	549	549
query18	2440	440	318	318
query19	200	170	138	138
query20	86	83	79	79
query21	211	133	110	110
query22	13082	13148	12808	12808
query23	13106	12541	12185	12185
query23_1	12132	12192	12069	12069
query24	7142	858	489	489
query24_1	474	480	484	480
query25	530	429	363	363
query26	1269	262	139	139
query27	2762	439	271	271
query28	4622	1946	1935	1935
query29	1524	578	437	437
query30	302	216	184	184
query31	900	764	637	637
query32	135	90	106	90
query33	504	297	230	230
query34	956	850	493	493
query35	746	765	648	648
query36	811	807	743	743
query37	138	107	90	90
query38	1769	1734	1676	1676
query39	694	696	671	671
query39_1	673	681	655	655
query40	217	116	97	97
query41	66	63	63	63
query42	84	85	82	82
query43	360	377	331	331
query44	1340	711	715	711
query45	177	176	167	167
query46	843	948	566	566
query47	3010	2935	2924	2924
query48	297	314	214	214
query49	564	394	295	295
query50	689	281	223	223
query51	10229	10594	10546	10546
query52	76	88	73	73
query53	192	203	157	157
query54	235	212	175	175
query55	76	84	66	66
query56	222	226	216	216
query57	1609	1589	1568	1568
query58	274	263	245	245
query59	2362	2361	2134	2134
query60	277	235	218	218
query61	152	183	148	148
query62	394	340	282	282
query63	202	161	166	161
query64	2719	912	782	782
query65	3449	3384	3417	3384
query66	1765	426	295	295
query67	20086	20346	20372	20346
query68	3073	1019	626	626
query69	379	288	251	251
query70	907	852	819	819
query71	304	228	203	203
query72	2780	2559	2288	2288
query73	509	535	295	295
query74	4604	4456	4313	4313
query75	2328	2312	1925	1925
query76	2297	1019	614	614
query77	341	403	292	292
query78	9102	8961	8478	8478
query79	860	897	525	525
query80	488	411	341	341
query81	529	317	272	272
query82	204	135	113	113
query83	204	202	177	177
query84	290	127	97	97
query85	772	425	361	361
query86	257	246	231	231
query87	2003	1938	1841	1841
query88	3666	2725	2699	2699
query89	333	299	265	265
query90	2134	189	184	184
query91	159	152	119	119
query92	96	85	90	85
query93	996	1032	568	568
query94	452	320	285	285
query95	605	338	387	338
query96	660	530	238	238
query97	2450	2394	2330	2330
query98	156	143	143	143
query99	767	772	646	646
Total cold run time: 232905 ms
Total hot run time: 152569 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.57 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 98679abb2b68d36033e4e8fe8e10078168beb193, data reload: false

query1	0.01	0.01	0.01
query2	0.10	0.05	0.05
query3	0.27	0.12	0.12
query4	1.61	0.12	0.12
query5	0.28	0.25	0.25
query6	1.18	0.69	0.69
query7	0.04	0.01	0.01
query8	0.05	0.04	0.04
query9	0.44	0.36	0.36
query10	0.60	0.56	0.60
query11	0.21	0.14	0.14
query12	0.18	0.14	0.14
query13	0.50	0.49	0.50
query14	0.97	0.96	0.96
query15	0.65	0.63	0.60
query16	0.35	0.35	0.32
query17	1.16	1.15	1.14
query18	0.24	0.21	0.21
query19	2.09	1.99	1.95
query20	0.02	0.01	0.02
query21	15.43	0.26	0.14
query22	4.51	0.06	0.05
query23	16.27	0.32	0.12
query24	3.21	0.64	0.40
query25	0.11	0.05	0.06
query26	1.28	0.25	0.16
query27	0.06	0.03	0.03
query28	1.74	0.60	0.43
query29	12.53	4.26	3.34
query30	0.29	0.15	0.14
query31	2.77	0.60	0.34
query32	3.27	0.61	0.52
query33	3.23	3.20	3.21
query34	15.62	4.03	3.39
query35	3.38	3.32	3.36
query36	0.55	0.44	0.42
query37	0.10	0.06	0.07
query38	0.05	0.04	0.04
query39	0.04	0.03	0.02
query40	0.17	0.14	0.15
query41	0.09	0.03	0.03
query42	0.03	0.04	0.03
query43	0.04	0.03	0.04
Total cold run time: 95.72 s
Total hot run time: 24.57 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage `` 🎉
Increment coverage report
Complete coverage report

@morningman

Copy link
Copy Markdown
Contributor

/review

@morningman

Copy link
Copy Markdown
Contributor

hi @laskoviymishka I will take a look at the second round AI review result. You don't need to handle it now

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two P2 issues remain: real Iceberg system-table tasks lose FE/BE compatibility during rolling upgrades, and empty delete-manifest entries omit the new key's retained partition-type graph from weighted cache admission. Both are inline below. No new P0/P1 finding was verified.

Reviewed all 21 changed files at 98679abb2b68d36033e4e8fe8e10078168beb193, the related callers/consumers, and primary Iceberg 1.11/1.12 sources. This was a static review: no builds, tests, storage requests, or cluster experiments were run. Added unit-test assertions and the author's reported test runs are not executed reviewer evidence.

The three previous findings are fixed on this head and were not reposted: Hudi/Avro is addressed by retaining Avro 1.12.1 in the shared dependency management and Hudi runtimes; blank HTTP type is normalized in catalog and probe maps; historical partition typing now uses the scan-bound spec map for data/delete readers and a type-sensitive key, with both cache-fill orders covered by a new unit case. No previous P0/P1 finding still applies.

The reviewed execution chains were:

CREATE/ALTER -> property validation -> common/flavor options -> catalog/FileIO
Historical/current scan -> bound specs -> cache -> residuals/delete index -> native ranges
System-table scan -> Java task serialization -> BE assignment -> JNI deserialization -> rows
Critical checkpoint Conclusion
Goal and proving tests SDK 1.12 adaptation is focused and has new HTTP/cache unit coverage; actual rolling task compatibility remains defective.
Change size and clarity Changes reuse the common options builder and existing scan/spec machinery; no unrelated source changes.
Concurrency and locks Immutable type keys preserve cross-query isolation; existing single-flight loading, publication fencing and deferred removal remain. Heavy manifest I/O stays outside cache compute/publication locks. No new lock-order defect verified.
Lifecycle and static initialization Readers are closed and copied; probe TCCL/close boundaries remain. Same-version Schema descriptors are unchanged. The incompatible metadata-task lifecycle is reported inline.
Configuration and dynamic updates No new global configuration. CREATE/ALTER validate merged catalog settings; rebuild applies the shared supported default. Explicit Apache settings require migration to URLConnection as the PR declares.
Binary, format and rolling compatibility Vendored DeleteFileIndex matches SDK 1.12 apart from Doris access adaptations; Avro remains 1.12.1 and runtime closures were inspected. Mixed-version JNI task compatibility is the first finding.
Thrift/protobuf IDs Not applicable: no definition changes.
Parallel paths Data/delete readers, synchronous/streaming/count enumeration, all catalog flavor bases and the separate storage probe were covered. Native $position_deletes does not use the incompatible JNI wire.
Special conditions Blank defaulting, missing-spec failure, historical type separation and partition validation have concrete rationale; delete checks match upstream applicability rules.
Functional and negative test coverage New JUnit cases cover defaults, blanks, rejection, probe property copying and historical cache orders. Actual mixed-version non-null metadata tasks and empty-delete weighted admission need coverage. No end-to-end regression execution verified.
Changed test results Unit assertions and option snapshots match intended behavior by inspection; no regression golden files changed.
Observability Existing fallback warnings/cache statistics remain; new version-skew error improves diagnosis but leaves the query unavailable. No new hot-path INFO logging.
Transactions and persistence No Doris journal, transaction or failover algorithm changes; catalog replay remains pure and snapshot/delete sequence selection was traced.
Data writes, atomicity and crashes Existing SDK/catalog write paths remain; no new Doris mutation protocol. No additional silent wrong-result or crash defect verified.
FE/BE variable passing No new field; the existing serialized task carries the changed Java graph. BE packages URLConnection for serialized FileIO properties.
Performance and memory Lazy enumeration and per-spec comparator reuse remain. New key-only schema retention bypasses cache weights for empty delete payloads: second inline finding.
Other issues and user concerns No additional user-provided focus. All candidates and risk items have evidence-backed dispositions; no changed file remains uncovered.

Remaining validation limits are static inspection, arbitrary custom FileIO/server overrides, and unexecuted dependency/cluster integration. Explicit or server-forced unsupported Apache client settings remain a declared compatibility restriction; no separate speculative finding was posted for them. No unresolved candidate remains in the supported scope.

Review converged after 2 round(s).

Comment thread fe/pom.xml Resolved
…n its weight

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69031

Problem Summary: `IcebergManifestEntryKey` now carries the bound partition
type (a `Types.StructType`) of the manifest's spec, so scans that bind a
manifest to different partition types get separate cached copies. When a
byte limit applies to the manifest cache (`meta.cache.iceberg.manifest.max-weight`,
`meta.cache.max-weight` or `external_meta_cache_max_weight`), every entry is
admitted with its estimated weight, but `estimateManifestKey` still counted
only the key object and the manifest path.

For a non-empty manifest this does not matter: its files share the key's
partition type instance, and the value estimate reaches it through them. A
delete manifest whose entries are all DELETED (iceberg keeps it in the
snapshot whose commit removed those delete files, and the cache-backed
planner reads every delete manifest) yields an empty value, so nothing
accounts for the partition type the key retains. Such entries were admitted
below their retained size, more so for wide partition specs, and the
difference stayed outside every manifest, catalog and global weight limit.

- `estimateManifestKey` now adds the key's partition type, using the
  existing `estimateIcebergType`. A partition type shared by several keys is
  counted once per key, which overestimates, the safe direction for
  admission.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Added IcebergManifestCacheTest#manifestKeyWeightCountsTheBoundPartitionType:
      with an empty delete-manifest value, an entry whose key has a 10-field
      partition type weighs at least nine `NestedField`s more than one with
      a 1-field type. It fails without the estimator change.
- Behavior changed: No
- Does this need documentation: No

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@morningman

Copy link
Copy Markdown
Contributor

run buildall

@morningman

Copy link
Copy Markdown
Contributor

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed commit 703a33ca3b189514e0c4152986af8608b76a7dae: one new P2 finding for legacy S3 remote-signing compatibility. The SDK upgrade is focused, but existing remotely signed catalogs need adaptation before their metadata reads remain usable. No new P0/P1 issue was verified.

The review converged in 2 rounds. The second round returned NO_NEW_VALUABLE_FINDINGS from both complete reviewers and the dedicated risk reviewer. All 22 changed files, their related control flow and tests were covered, with every candidate and risk focus explicitly accepted, deduplicated or dismissed. No additional user-provided focus was supplied.

Existing review context was independently checked and not reposted:

  • Hudi Avro P1 is fixed: the shared version remains 1.12.1. No existing P0/P1 finding still applies, so existing_blocking_comment_ids is empty.
  • The blank HTTP-client default and historical partition-type issues are fixed: both catalog/probe maps normalize blank values, and data/delete readers, residuals and the index use the same scan-bound specs with typed cache keys.
  • Cache-key accounting P2 is partly fixed. Direct partition fields/types are counted, but a partition predicate populates the retained StructType's Schema/name/id/accessor indices, which estimateIcebergType omits. An empty delete-manifest value cannot compensate for that graph. This remains within the original issue and is not a new inline finding.
  • Rolling-upgrade task compatibility P2 still applies. Real metadata tasks carry changed BaseFile/PartitionData graphs; the Schema shim and improved exception do not make 1.11/1.12 FE/BE tasks interoperable. The author declined a fix; this is retained as a known limitation, not reposted.

Core invariants checked include pinned snapshot visibility, delete-file association, cache ownership/accounting and exception propagation. Native OLAP visible-version, MoW bitmap and BE allocator code are unchanged.

Skill checkpoint Static conclusion and evidence
Goal and proving tests Iceberg SDK is raised to 1.12 with transport, delete-index, manifest-reader and diagnostics adapters; remotely signed metadata regression M2 and known mixed-version task limitation remain. Added JUnit tests support individual adapters, not a complete end-to-end upgrade proof.
Small, clear, focused scope All 22 changed files relate to the SDK upgrade, adapters and tests; no unrelated implementation expansion.
Concurrency, lock costs/order Concurrent queries share immutable cache keys/payloads; single-flight loads run outside publication key locks, invalidation leases fence publication. Streaming iterator has one consumer, and streaming avoids mutable query tallies. No new lock-order defect substantiated.
Lifecycle/static initialization Readers are closed and copied records retained; cache reservations/invalidation lifecycle stays in the shared framework. Plugin child-first dependencies remain isolated; Schema source and UID guard are unchanged for same-version SDK. No cross-TU/static-order change.
Configuration/dynamic changes Existing http-client.type now defaults blank/unset to urlconnection; apache rejected at CREATE/ALTER while of()/replay stays pure. Rebuild consumes changed catalog options. Legacy signer keys need migration (M2). No new FE/BE runtime config added.
Symbols/storage/rolling compatibility Vendored DeleteFileIndex mirrors SDK 1.12 shape; Avro stays 1.12.1 and Caffeine is bundled 3.2.4. Real Java task graphs still fail across 1.11/1.12 (K5). Remote signer protocol compatibility M2.
Thrift/Proto branch field IDs No gensrc changes or new protocol field IDs; not applicable.
Parallel code paths Both data/delete readers use scan-bound specs across sync/stream/count. Catalog and storage-probe maps share HTTP normalization; scanner bundles URLConnection. REST/server signer property path remains a finding.
Special conditions Blank-type normalization handles a concrete Apache5 default failure; spec checks fail loudly; conditional SDK partition matching matches upstream. No speculative source change added.
Test coverage/negative cases/modularity Added tests inspect blank/default/explicit HTTP config, forbidden apache, probe settings, two cache warm orders, empty-key weight and serialization error causes. Remote signing, actual old/new task interoperability and populated empty-key Schema graph not proven by these tests. No builds/tests permitted or run.
Test result changes No regression .out/golden changes; JUnit expectations inspected, not executed.
Observability New skew exception includes SDK version and retains cause; cache failures keep existing warnings/failure metrics. No new metric requirement identified for these adapters.
Transactions/persistence/failover No transaction or journal/write/replay format changes; statement validation is kept out of property reconstruction.
Data writes/atomicity/crash No Doris data-write or transaction code changed; vendored delete validation protects reads and fails loudly. No new crash/leak path substantiated.
New FE/BE variable propagation No new wire variable; existing serialized_split stays unchanged and therefore retains K5's mixed-version limit. HTTP choice is carried by serialized FileIO properties.
Performance/CPU/memory Shared lazy scan enumeration remains; added typed-key variants are needed for correctness. K4's direct type fields are counted, populated lazy Schema graph remains a known accounting gap. avgValueSizes suspicion M1 dismissed because supported manifest reads do not retain it.
Other issues/user focus No additional user focus. All candidates remain explicit; M2 is one distinct new P2, K4/K5 already covered.

Validation was static only: no builds, tests, services or source modifications were performed. Added JUnit assertions, upstream SDK sources and dependency symbols were inspected; author-reported test results were not treated as executed evidence. Real remote signing, deployed plugin/classloader behavior, FE/BE interoperability and heap measurements remain unexecuted. The new tests do not establish remotely signed manifest reads, real mixed-version task compatibility or populated empty-key Schema accounting. No changed-file coverage gap or unresolved distinct code candidate remains.

Review converged after 2 round(s).

Comment thread fe/pom.xml Resolved
@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29260 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 703a33ca3b189514e0c4152986af8608b76a7dae, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17612	5624	5542	5542
q2	2120	321	261	261
q3	10213	1394	851	851
q4	4686	466	341	341
q5	7428	785	538	538
q6	194	193	162	162
q7	747	787	610	610
q8	9251	1355	1164	1164
q9	5514	4282	4226	4226
q10	6814	1300	1041	1041
q11	438	258	239	239
q12	630	396	282	282
q13	18104	3615	2980	2980
q14	278	265	242	242
q15	q16	739	717	651	651
q17	1192	735	588	588
q18	7090	6220	6186	6186
q19	1100	959	615	615
q20	368	339	222	222
q21	4629	2260	2396	2260
q22	357	306	259	259
Total cold run time: 99504 ms
Total hot run time: 29260 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6151	6065	6105	6065
q2	673	569	547	547
q3	5196	5416	4965	4965
q4	2010	2107	1530	1530
q5	5269	5186	5927	5186
q6	258	199	160	160
q7	2331	1979	1855	1855
q8	3152	2793	2711	2711
q9	8127	8046	8112	8046
q10	3858	3712	3418	3418
q11	641	433	432	432
q12	690	730	528	528
q13	3687	3964	3176	3176
q14	313	316	291	291
q15	q16	712	730	648	648
q17	8338	7517	7020	7020
q18	13177	12251	13068	12251
q19	919	795	772	772
q20	2184	2181	1962	1962
q21	5741	4694	4763	4694
q22	485	448	425	425
Total cold run time: 73912 ms
Total hot run time: 66682 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152423 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 703a33ca3b189514e0c4152986af8608b76a7dae, data reload: false

query5	4312	604	460	460
query6	427	212	192	192
query7	4824	446	226	226
query8	315	169	155	155
query9	8756	3907	3928	3907
query10	466	303	261	261
query11	6094	3836	3524	3524
query12	145	90	89	89
query13	1241	420	314	314
query14	6129	4012	3720	3720
query14_1	3510	3479	3504	3479
query15	206	198	177	177
query16	950	445	414	414
query17	844	652	547	547
query18	2426	431	306	306
query19	209	158	138	138
query20	86	85	85	85
query21	209	137	114	114
query22	13022	12991	12835	12835
query23	13683	12939	12461	12461
query23_1	12612	12691	12498	12498
query24	7100	830	466	466
query24_1	490	470	475	470
query25	533	420	363	363
query26	1266	265	145	145
query27	2749	438	275	275
query28	4615	1940	1953	1940
query29	1563	603	454	454
query30	299	220	188	188
query31	1017	934	813	813
query32	142	109	93	93
query33	513	306	249	249
query34	898	890	501	501
query35	750	769	658	658
query36	830	807	728	728
query37	130	101	90	90
query38	1820	1752	1696	1696
query39	807	833	761	761
query39_1	753	742	742	742
query40	215	127	101	101
query41	72	67	66	66
query42	90	90	84	84
query43	370	383	337	337
query44	1301	700	712	700
query45	179	178	162	162
query46	844	967	565	565
query47	2949	3058	2941	2941
query48	332	306	212	212
query49	568	393	293	293
query50	685	268	218	218
query51	10593	10486	10610	10486
query52	83	81	68	68
query53	187	206	159	159
query54	257	223	197	197
query55	81	71	62	62
query56	250	220	194	194
query57	1595	1569	1538	1538
query58	288	263	277	263
query59	2137	2178	1931	1931
query60	298	263	222	222
query61	147	143	145	143
query62	400	344	281	281
query63	195	160	166	160
query64	2711	944	793	793
query65	3296	3240	3221	3221
query66	1773	444	300	300
query67	20248	20365	20286	20286
query68	2914	1013	624	624
query69	375	293	247	247
query70	871	793	759	759
query71	288	234	210	210
query72	2761	2579	2312	2312
query73	510	525	293	293
query74	4595	4457	4323	4323
query75	2362	2315	1958	1958
query76	2301	1020	608	608
query77	352	383	284	284
query78	9751	9871	9179	9179
query79	949	911	522	522
query80	818	436	342	342
query81	584	328	275	275
query82	574	137	109	109
query83	282	199	188	188
query84	311	128	101	101
query85	1019	445	369	369
query86	350	237	227	227
query87	2017	1957	1800	1800
query88	3646	2728	2701	2701
query89	350	299	249	249
query90	1700	180	180	180
query91	155	149	122	122
query92	89	91	89	89
query93	1012	1009	582	582
query94	529	297	263	263
query95	585	339	308	308
query96	673	528	237	237
query97	2461	2453	2319	2319
query98	162	151	164	151
query99	779	761	647	647
Total cold run time: 234724 ms
Total hot run time: 152423 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.63 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 703a33ca3b189514e0c4152986af8608b76a7dae, data reload: false

query1	0.00	0.00	0.01
query2	0.10	0.05	0.05
query3	0.26	0.11	0.12
query4	1.61	0.12	0.12
query5	0.24	0.25	0.24
query6	1.16	0.69	0.69
query7	0.04	0.01	0.01
query8	0.05	0.04	0.03
query9	0.42	0.31	0.35
query10	0.61	0.57	0.60
query11	0.20	0.15	0.13
query12	0.18	0.16	0.14
query13	0.48	0.49	0.50
query14	1.02	1.01	1.01
query15	0.64	0.59	0.62
query16	0.35	0.33	0.34
query17	1.22	1.15	1.13
query18	0.22	0.21	0.21
query19	2.11	2.06	1.93
query20	0.02	0.01	0.01
query21	15.50	0.27	0.14
query22	4.48	0.06	0.06
query23	16.24	0.31	0.12
query24	3.08	0.60	0.40
query25	0.11	0.07	0.06
query26	1.35	0.24	0.14
query27	0.05	0.04	0.05
query28	2.40	0.61	0.40
query29	12.51	4.33	3.47
query30	0.28	0.14	0.13
query31	2.77	0.58	0.33
query32	3.23	0.61	0.52
query33	3.15	3.22	3.24
query34	15.47	3.98	3.38
query35	3.35	3.35	3.35
query36	0.55	0.41	0.43
query37	0.10	0.06	0.07
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.17	0.15	0.14
query41	0.08	0.04	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 95.97 s
Total hot run time: 24.63 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 0.00% (0/45) 🎉
Increment coverage report
Complete coverage report

@morningman
morningman merged commit fd268c2 into apache:master Oct 15, 2026
49 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

PR approved by anyone and no changes requested.

@github-actions github-actions Bot added the approved Indicates a PR has been approved by one committer. label Oct 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

PR approved by at least one committer and no changes requested.

morningman added a commit that referenced this pull request Oct 27, 2026
#69135)

### What problem does this PR solve?

Issue Number: #68916 

Related PR: #69031

Problem Summary: The Iceberg REST catalog spec now lets a catalog return
`labels` with each table load (apache/iceberg#15750): catalog-owned,
per-request metadata such as ownership, classification or cost
attribution, at the table level (`object-labels`) and per field (keyed
by `field-id`). Labels are not part of the table metadata, have no
snapshots and are never written to `metadata.json`. Iceberg 1.12.0
exposes them on the loaded table via `SupportsLabels#labels()`. Doris
had no way to show them.

Add a `t$labels` system table for iceberg tables in a REST catalog:

```sql
    SELECT * FROM rest_ctl.db.tbl$labels;
    scope  | field_id | field_name | key            | value
    object | NULL     | NULL       | owner          | team-a
    field  | 2        | email      | classification | pii
```

One row per label. `field_name` is resolved against the current table
schema and is NULL for a field id that is no longer in it (a dropped
column). The schema mirrors iceberg's proposed `LabelsTable`.

Implementation:

- Keep labels when Doris rebuilds a loaded table. iceberg's REST client
attaches them to the loaded `BaseTable` as a transient field; they are
not table metadata, so a `BaseTable` rebuilt from its `TableOperations`
must pass them explicitly.
`IcebergTableCache.TableLease#snapshotReadTable` (cached reads),
`IcebergStatementScope#snapshotReadTable` (statement reads) and
`IcebergScanPlanProvider#wrapTableForScan` (Kerberos FileIO wrap) used
constructors that reset labels to `Labels.EMPTY`, so every read saw no
labels; they now pass `baseTable.labels()`.
- `labels` is not a `MetadataTableType`, so it is handled next to the
SDK metadata tables rather than through `MetadataTableUtils`.
`IcebergConnectorMetadata` lists and resolves it only when the catalog
flavor is `rest` (no other catalog returns labels), and serves its fixed
schema and column handles without loading the base table.
- `IcebergScanPlanProvider` plans it as one split. A new split-package
helper `org.apache.iceberg.IcebergLabelsDataTask` builds an iceberg
`StaticDataTask` (package-private in the SDK) holding the label rows,
projected to the requested columns in BE's required-field order; its
metadata `DataFile` is synthesized, so no storage request is made. The
task is serialized like every other static metadata table, so BE's
`IcebergSysTableJniScanner` reads it with no BE change.
- The ordered system-table projection is extracted into
`projectSystemTableSchema` and shared with the existing path, and the
base-table load is split out of `resolveSysTable` as
`resolveSysBaseTable`.
- Labels are not versioned: like `$snapshots`/`$history`, the snapshot
pin of the handle is ignored, and `$labels` is exempt from the
resolved-empty-snapshot fence, so a table with no commit still shows its
labels.

Labels reflect the table load the statement used, so they follow the
iceberg table cache (`meta.cache.iceberg.table.ttl-second`); REFRESH
TABLE picks up new labels. Like the other system tables, a REST catalog
that requires server-side scan planning rejects `$labels`.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: morningman <yunyou@selectdb.com>
morningman added a commit that referenced this pull request Nov 6, 2026
…itialize (#70164)

### What problem does this PR solve?

Issue Number: None

Related PR: #66913, #66914

Problem Summary:

**In short.** This ports from branch-4.x #66913 the cleanup of an
Iceberg `HiveCatalog` whose initialization fails after it has created
its FileIO: on master, nothing closes that FileIO. With the FileIOs
master configures, the leaked object holds no native resource today, so
this is hygiene that keeps a FileIO with real resources from leaking
once per failed catalog creation.

**Background.** `DorisHiveCatalog` (fe-connector-iceberg, used for
Iceberg on HMS) extends Iceberg's `HiveCatalog` and owns the FileIO the
catalog creates (#66914). In Iceberg 1.12, `HiveCatalog#initialize`
creates the FileIO first, then the Hive client pool, and only then the
`CloseableGroup` that closes the FileIO, the KMS client and the metrics
reporter. #66913, the branch-4.1 port of #66914, closes the FileIO when
initialization fails; master's `DorisHiveCatalog` does not.

**The problem, and what it cost.** When `CachedClientPool` fails (an
unknown element in `client-pool-cache-keys`, a `clients` that is not a
number) or the metrics reporter fails to load (`metrics-reporter-impl`),
the catalog has a FileIO but no group: `HiveCatalog#close` closes
nothing, and `DorisHiveCatalog` has not captured the FileIO yet. The
catalog properties reach Iceberg as the user gave them, and
`IcebergConnector` caches only a catalog that initialized, so each
metadata access on such a catalog creates and drops another FileIO.
Today that is only garbage: master's HMS catalogs use `HadoopFileIO`,
whose `close` does nothing, and `ResolvingFileIO` and `S3FileIO` create
their clients lazily.

**How this PR fixes it.** When `HiveCatalog#initialize` throws,
`DorisHiveCatalog#initialize` closes the FileIO the catalog created and
rethrows; a failure to close is added to the initialization failure as
suppressed. The FileIO is null when loading the FileIO itself failed,
and then there is nothing to close. Not ported from #66913: its
`close()` changes, since Iceberg 1.12 (#69031) closes the FileIO in
`HiveCatalog#close` itself, and its `DorisHadoopCatalog`. The hadoop
flavor has the same order (`HadoopCatalog` creates the FileIO before the
lock manager), but master uses Iceberg's `HadoopCatalog`, and a subclass
would change the catalog-impl mapping without freeing anything today.

**Results.**

| `client-pool-cache-keys` with an unknown element | Before | After |
|---|---|---|
| `DorisHiveCatalog#initialize` | throws `IllegalArgumentException`, the
FileIO stays open | throws `IllegalArgumentException`, the FileIO is
closed |

Co-authored-by: 924060929 <lanhuajian@selectdb.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by one committer. reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants