morningman opened a new pull request, #65970:
URL: https://github.com/apache/doris/pull/65970

   ### What problem does this PR solve?
   
   Issue Number: #65185
   
   Related PR: #65893, #65733, #65502, #65473, #65329
   
   Problem Summary:
   
   Part of the catalog-SPI migration tracked in #65185, which decouples the 
built-in
   connectors (hive / iceberg / hudi / paimon) from FE core into loadable 
plugins.
   
   An independent clean-room review of the migrated catalog SPI raised 28 
abstraction-mismatch
   findings (data/predicate/schema/partition/stats/write granularity). Each was 
re-verified
   against the current tree in a two-stage adversarial pass (independent 
investigation →
   red-team). Most collapsed on inspection: 2 were refuted (#5, #17), 4 were 
already fixed
   upstream (#3, #4, #6, #28-core), and the bulk of the rest were dead code, 
intentional
   legacy parity, or estimate-only skew. This PR lands the genuinely actionable 
subset, plus
   a few adjacent connector runtime/build fixes discovered alongside. The 
verification
   workspace (the survey, seven per-category analyses, the rollup, and per-fix 
design/summary
   notes) is included under `plan-doc/catalog-spi-mismatch/`.
   
   Each fix is a standalone commit; connector changes are connector-local 
(fe-core keeps
   shrinking, per the migration's "fe-core only sheds source-specific code" 
rule).
   
   **1. Correctness — user-visible fixes**
   
   - **paimon time-travel read across a rename no longer crashes BE (#2).** For 
a
     plugin-driven read that pins a historical MVCC snapshot with a *distinct* 
schema
     (`FOR VERSION/TIME AS OF`, `@branch/@tag`), 
`PluginDrivenScanNode.buildColumnHandles`
     now resolves the connector column handles at the *pinned* schema via a new 
opt-in
     `ConnectorTableOps.getColumnHandles(session, handle, 
ConnectorMvccSnapshot)` overload
     (capability `supportsColumnHandleSnapshotPin`, default false, implemented 
only by
     paimon). Previously a mixed projection (a surviving column plus a renamed 
one) resolved
     handles against the *latest* schema, silently dropped the renamed column's 
handle, and
     still sent it to BE as a scan slot absent from paimon's field-id 
dictionary — a BE
     `StructNode` `std::out_of_range`/SIGABRT. This is a **crash fix**, not a 
wrong-results
     fix. iceberg was already immune (it rebuilds its field-id dictionary from 
the full
     pinned schema) and is untouched. A capability-gated fail-loud guard now 
throws a
     `UserException` (surfaced through the split-assignment error channel) if a 
bound column
     is present in the pinned schema but still lacks a handle, instead of 
degrading into a BE
     crash.
   
   - **hudi decimal partition predicate no longer prunes matching rows (#1).**
     `HudiConnectorMetadata.extractLiteralValue` now renders a `BigDecimal` 
literal via
     `stripTrailingZeros().toPlainString()` (gated on `instanceof BigDecimal`; 
all other
     literals unchanged). Before, a `decimal(8,4)` predicate rendered as 
`"1.0000"` and never
     string-equalled the Hive-canonical stored partition value `"1"`, so the 
partition was
     pruned and its rows silently dropped from the result. Mirrors the 
rendering hive already
     uses.
   
   - **paimon `partition_values()` TVF handles DATE/null (#14).**
     `PaimonConnectorMetadata` now puts the already-rendered spec (DATE 
formatted via
     `DateTimeUtils.formatDate`, genuine null normalized to the Hive 
default-partition
     sentinel) into the `ConnectorPartitionInfo` value map, aligning it with 
hive/iceberg
     which already carry decoded canonical strings. Before, the raw paimon spec 
carried DATE
     as an epoch-day string, which the active TVF feeder parsed and threw on — 
failing the
     whole `partition_values()` query — and rendered null as the internal 
sentinel string
     rather than SQL NULL.
   
   **2. CBO estimate accuracy — plans only, results unchanged (#15)**
   
   - Time-travel row-count is now estimated at the pinned snapshot instead of 
the latest
     table. `ConnectorStatisticsOps` gains an opt-in
     `getTableStatistics(session, handle, ConnectorMvccSnapshot)` overload;
     `StatementContext.getVersionedSnapshot` exposes the single versioned pin 
for a table;
     `PluginDrivenExternalTable.getRowCount` computes the count at that 
snapshot (bypassing
     and not polluting the latest-keyed cross-statement cache) and falls back 
to the cached
     latest estimate when a table cannot count at the snapshot or there is no 
statement
     context. iceberg reads the pinned snapshot's summary (`table.snapshot(id)` 
vs
     `currentSnapshot()`); paimon sums the pinned split row counts. This only 
affects the
     cardinality fed to join reorder / build-side selection; query results were 
correct before
     and after.
   
   **3. User-signed-off enhancements (#10, #12, #16)**
   
   - **iceberg column write default (#10).** 
`IcebergConnectorMetadata.parseSchema` now
     carries `field.writeDefault()` through the new
     `IcebergSchemaUtils.writeDefaultToDorisString` (reusing the read-side 
human-string form;
     returns null for missing defaults, complex, and binary-like types). A v3 
write default
     now survives a schema refresh, so `DESCRIBE` shows it and an INSERT that 
omits the column
     applies it instead of writing NULL. This only populates FE `Column` 
metadata and is
     orthogonal to the read-default (initialDefault) BE path from #65502.
   
   - **paimon nested STRUCT field comment (#12).** A `COMMENT` on a field 
nested inside a
     STRUCT column is now carried through both the paimon write path (4-arg 
`DataField`) and
     read path (`ConnectorType.structOf(..., comments)`), and the shared
     `ConnectorColumnConverter.convertStructType` now threads per-field comment 
and
     nullability (connectors that leave them unset are byte-identical to 
before, so only
     paimon changes). The nested comment is visible via `SHOW CREATE TABLE` and 
the on-disk
     `$schemas.fields`; `DESCRIBE` omits nested-field comments for every table 
by design, so
     it is not asserted there.
   
   - **SqlCache quiet-window gate uses a real wall clock (#16).** 
`CacheAnalyzer` now computes
     the quiet-window as `now - max(latestPartitionUpdateMillis)` sourced from 
a new
     wall-clock accessor 
(`MTMVRelatedTableIf.getNewestUpdateTimeMillisForCache`), separate
     from the raw version token used for BE PCache staleness. iceberg fills it 
from
     `last_updated_at` micros/1000 while its monotonic version marker stays in 
micros
     (`ConnectorMvccPartitionView` renamed to drop the misleading `Millis` 
unit; pure rename,
     no behavior change). Before, iceberg's ~1.7e15-micros token clamped `now` 
via `Math.max`
     and permanently suppressed SqlCache for a quiet iceberg table (and any 
query joining one).
     This is a **cache-eligibility (availability) fix**; staleness is still 
guarded
     independently by the unchanged version-token equality check.
   
   **4. Connector-SPI shape convergence — refactor, no behavior change (#7, #8, 
#9)**
   
   - **#8** lifts source-specific methods off the shared transaction contracts 
into narrow
     opt-in capability interfaces: `RewriteCapableTransaction` (iceberg 
compaction rewrite)
     and `WriteBlockAllocatingConnectorTransaction` (maxcompute block 
allocation) replace the
     methods previously declared on `ConnectorTransaction`, and the maxcompute 
write-block
     concept is removed from the generic fe-core `Transaction` interface
     (new `WriteBlockAllocatingTransaction extends Transaction`). Call sites
     (`FrontendServiceImpl`, `ConnectorRewriteDriver`, 
`PluginDrivenTransactionManager`) now
     `instanceof`-gate the capability. Transaction-id granularity, 
commit/rollback,
     update-count, and every generic method are unchanged; the user-facing 
error strings are
     byte-identical.
   - **#7 / #9** are javadoc-only corrections: narrow 
`ConnectorWriteHandle.getWriteContext`
     to "the static partition spec" (its only producer), and rewrite the 
`ConnectorBucketSpec`
     javadoc to drop the dead `iceberg_bucket`/`hive_hash` algorithm names and 
document the
     real table-level `DISTRIBUTE BY` values consumed by hive. No code change.
   
   **5. Dead-code & comment cleanup — no behavior change (#21, #23, #25, #28)**
   
   - Remove the never-constructed, never-read `ConnectorDeleteFile` (#21) and
     `ConnectorDomain`/`ConnectorRange` pushdown abstraction (#23) from 
connector-api, with
     their vestigial accessors (`ConnectorScanRange.getDeleteFiles`,
     `ConnectorFilterConstraint.getColumnDomains`); iceberg merge-on-read 
deletes use their
     own untouched path.
   - Add `equals`/`hashCode`/`toString` to `ConnectorMvccSnapshot` for parity 
with its
     value-object siblings (#25; additive, no current Map/Set-key usage).
   - Reword stale "dormant until SPI_READY_TYPES" comments in the hive 
connector now that the
     HMS→SPI flip is complete (#28; comment text only, verified no non-comment 
lines changed).
   
   **6. Adjacent connector runtime/build fixes**
   
   - **paimon-scanner classpath**: bundle `hive-common` + `hive-shims-common` 
(pinned to
     `${hive.version}`) and `hive-standalone-metastore` into the paimon-scanner 
assembly so
     HMS-backed Paimon reads link — fixing BE `NoClassDefFoundError` on
     `org/apache/hadoop/hive/conf/HiveConf` and 
`.../metastore/api/NoSuchObjectException`
     after #65733 slimmed the shared BE classpath. Build/packaging only.
   - **preload-extensions classpath**: restore `net.java.dev.jna:jna` / 
`jna-platform`
     `5.13.0`, fixing all trino-connector cases failing with
     `NoSuchMethodError com.sun.jna.Native.load` (oshi/Udev) after fe-common 
went trino-free
     and the older hadoop-hdfs jna won the parent-first classpath. 
Build/packaging only.
   - **iceberg flat MODIFY COLUMN**: a `MODIFY COLUMN` that omits `COMMENT` now 
preserves the
     field's existing doc instead of clearing it (threads a `commentSpecified` 
flag, parity
     with the nested path / legacy ops), and a complex→primitive type change is 
now rejected
     with a clean `Modify column type from complex to primitive is not 
supported` message
     instead of leaking a raw iceberg type-diff error (symmetric with the 
existing
     primitive→complex guard; the operation was already unsupported).
   
   **7. Review workspace (docs, `plan-doc/`)**
   
   - Add `plan-doc/catalog-spi-mismatch/`: the abstraction-mismatch survey, 
seven per-category
     analyses (A–G), the verification rollup, HANDOFF/TASKLIST, and per-fix 
design/summary
     notes. `plan-doc/` is already tracked on this migration branch.
   
   Findings verified and intentionally **not** changed (refuted, already-fixed 
upstream, or
   intentional legacy parity — e.g. #3/#4/#5/#6/#11/#13/#17/#18/#19/#22/#24) 
are recorded with
   evidence in `plan-doc/catalog-spi-mismatch/analysis-00-rollup.md`. The 
`ReaderType`
   unification (#27) is left as an independent design task.
   
   ### Release note
   
   None
   
   ### Check List (For Author)
   
   - Test <!-- At least one of them must be included. -->
       - [x] Regression test
       - [x] 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 <!-- Add your reason?  -->
   
   - Behavior changed:
       - [ ] No.
       - [x] Yes. <!-- Explain the behavior change -->
           - paimon time-travel mixed-projection read across a rename no longer 
crashes BE (#2).
           - hudi decimal partition predicate no longer prunes matching rows 
(#1).
           - paimon `partition_values()` TVF handles DATE/null (#14).
           - iceberg column write default is surfaced for DESCRIBE and 
INSERT-omitted fill (#10).
           - paimon nested STRUCT field comment carried through create/read 
(SHOW CREATE TABLE) (#12).
           - iceberg tables become SqlCache-eligible (availability; staleness 
still guarded) (#16).
           - iceberg flat MODIFY COLUMN preserves an omitted comment / rejects 
complex→primitive.
           - Time-travel CBO row-count estimate is snapshot-accurate (plans 
only; results unchanged) (#15).
           - Refactor/cleanup items (#7/#8/#9/#21/#23/#25/#28) and the 
classpath fixes carry no logic change.
   
   - Does this need documentation?
       - [x] No.
   
   ### Check List (For Reviewer who merge this PR)
   
   - [ ] Confirm the release note
   - [ ] Confirm test cases
   - [ ] Confirm document
   - [ ] Add branch pick label <!-- Add branch pick label that this PR should 
merge into -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to