[fix](paimon) Harden JNI reader options and transport - #66247
Conversation
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
run buildall |
|
/review |
There was a problem hiding this comment.
Request changes: five blocking correctness and compatibility issues remain in the Paimon hardening paths.
Checkpoint conclusions:
- Goal and proof: the patch improves option validation, JNI identifier framing, raw-parameter log redaction, ALTER rollback, and thread-count sampling, but it does not accomplish the goal on all supported inputs and paths. The added tests do not cover the five blockers.
- Scope and clarity: the change is generally focused and reuses shared validators, although the generic
CatalogMgrrollback change broadens the impact of connector-specific validation. - Concurrency: the cached thread counter has sound volatile publication, synchronized refresh, retry, and wrap-safe TTL behavior. Failed ALTER is not atomic against concurrent lazy catalog initialization (MAIN-4).
- Lifecycle: Paimon
Table.copyis relation-local and does not mutate cached base-table options; no C++ static-initialization-order or ownership issue was found. Failed ALTER can nevertheless leave initialized derived catalog state alive after raw-map rollback (MAIN-4). - Dynamic options/configuration: catalog and relation reader overrides are observed without restart and their new bounds are clear, but equivalent values inherited from the physical Paimon table bypass validation (MAIN-3).
- Compatibility: retaining the legacy JNI field is rolling-upgrade-friendly only on the V2 producer. The still-supported V1 producer omits the safe payload (MAIN-1), nested type framing remains delimiter-unsafe (MAIN-2), and persisted pre-upgrade catalog options can prevent initialization (MAIN-5).
- Parallel and conditional paths: V2, V1/load routing, catalog, relation, and physical option sources were traced. The missed V1 and physical-table paths are blockers; the added validation conditions and error conversions are otherwise understandable.
- Tests/results: helper unit tests cover basic parsing, validation, redaction, and cache TTL. The P0 success blocks assert only absence of exceptions, leave Scanner V2 enabled, and omit nested names, unsafe physical options, a latch-driven ALTER race, and image/edit-log upgrade coverage. No generated expected-result file was added.
- Observability: raw scanner parameters are no longer logged and the cached JVM thread gauge is safe; no additional metric or log blocker was found.
- Persistence/transactions/data writes: edit-log ordering is correct in the single-threaded success/failure paths and no data-write transaction path changes here. Concurrent failed ALTER can expose unjournaled derived state (MAIN-4), while reload of existing persisted properties is incompatible (MAIN-5).
- Cross-module transport: no new FE-to-BE variable is introduced, but the BE-to-Java JNI schema parameter was updated in only one producer and its parallel type payload remains unsafe (MAIN-1 and MAIN-2).
- Performance: the JVM thread-count cache removes repeated thread walks without a material lock bottleneck. Unsafe physical manifest parallelism can still create a zero-permit wrapper or enlarge Paimon's JVM-static executor (MAIN-3).
- Additional user focus: no extra focus was supplied; the entire changed-file set was reviewed.
Validation was static only: the authoritative review prompt prohibits builds/tests, and this checkout lacks .worktree_initialized and thirdparty/installed. No build or test result is claimed.
FE UT Coverage ReportIncrement line coverage |
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
TPC-H: Total hot run time: 29850 ms |
TPC-DS: Total hot run time: 177722 ms |
ClickBench: Total hot run time: 25.02 s |
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
FE Regression Coverage ReportIncrement line coverage |
|
run buildall |
|
/review |
TPC-H: Total hot run time: 29454 ms |
There was a problem hiding this comment.
Two blocking correctness gaps remain:
- The new Base64 list protocol still maps one empty top-level identifier to the same payload as zero projected fields, so the Java constructor rejects a reachable external Paimon schema on field/type cardinality.
- Physical-plus-catalog options are validated before relation-scoped options are copied, so a safe relation override cannot take the documented precedence over an unsafe physical value.
Critical checkpoint conclusions:
- Goal and proof: the PR substantially adds bounded Paimon reader options, physical/catalog validation, relation-local copies, delimiter-safe transport, log redaction, detached ALTER validation, replay compatibility, and cheaper metrics. The two findings above prevent the full advertised identifier and precedence behavior. Existing tests do not cover either failing case.
- Scope and clarity: production changes are focused on Paimon/JNI behavior plus one generic ExternalCatalog validation hook and one shared JNI type parser extension. No unrelated source changes were found.
- Concurrency and locking: detached Paimon validation does not publish tentative CatalogProperty state; accepted updates reset synchronized ExternalCatalog objects and invalidate Paimon caches. The global thread counter uses synchronized refresh and volatile publication with intentional one-second staleness. No additional deadlock or stale-publication defect was found.
- Lifecycle and error handling: V1/V2 scanner construction and existing JNI cleanup remain aligned; mixed encoded schema halves fail loudly. Catalog rollback/replay/reset paths preserve prior or journaled state. No new resource leak or swallowed status was substantiated.
- Configuration and dynamic behavior: no Doris runtime config item is added. Catalog ALTER resets derived state, relation options use per-handle Table.copy, and unsafe values are range-checked; MAIN-2 is the remaining ordering error in the precedence chain.
- Compatibility and parallel paths: legacy schema parameters remain as fallback, V1 and V2 now emit the paired protocol, and persisted legacy catalog keys remain raw but inactive. Ordinary, branch, snapshot, system-table, cache-loader, planning, and JNI serialization paths were traced. MAIN-1 affects both scanner routes; MAIN-2 affects ordinary and system-table relation copies.
- Persistence, transactions, and writes: the catalog edit-log replay path was checked and retains loadability without applying unsafe legacy options. The PR does not alter Doris data transaction or storage-format semantics.
- Testing: review-time builds/tests were forbidden by the authoritative prompt and none were run in this review environment. CI was observed separately immediately before submission; its evolving state is not claimed as review-time test evidence. Changed tests cover the existing five review fixes but omit
{}versus{""}framing and safe relation override of an unsafe physical value. - Observability and performance: raw credential-bearing scanner parameter logging is removed, fixed summary fields remain, and the JVM thread-count sample removes repeated ThreadMXBean allocation. No additional observability or material performance regression was found.
- FE/BE propagation and nullability: both legacy and V2 BE producers publish the new paired Java parameters; no new FE-to-BE thrift variable or nullable-column manipulation is introduced.
- User focus: no additional user-provided focus was supplied; the full PR was reviewed.
The five existing inline threads were rechecked and not duplicated: legacy V1 producer parity, nested type framing, no-override physical option validation, detached ALTER validation, and persisted-catalog compatibility are addressed at the reviewed head.
TPC-DS: Total hot run time: 177617 ms |
ClickBench: Total hot run time: 24.9 s |
|
run buildall |
|
/review |
There was a problem hiding this comment.
Reviewed the full authoritative 22-file bundle; no additional user focus was supplied.
The four inline P1 findings are distinct remaining routes around the new effective-option guard: a read-only system-table wrapper hides its option-bearing data table, row-count planning runs outside PaimonScanNode, partition snapshot loading scans a raw physical handle before overrides, and a fallback reader exposes only the main branch's options.
Checkpoint conclusions:
- Goal and tests: direct data-table option precedence and both JNI scanner protocols are covered, but the changed tests do not exercise the four real wrapper/pre-planning/fallback routes above.
- Scope, parallel paths, and special conditions: V1/V2 JNI framing, data/system/incremental/options/no-options paths, empty and nested identifiers, partitioned metadata, row-count loading, and fallback branches were traced; only the four inline paths remain defective.
- Concurrency, lifecycle, persistence, and compatibility: detached catalog ALTER validation, single live publication/reset, replay/image compatibility, and legacy-key filtering are sound; no additional race or upgrade defect remains.
- Configuration and performance: valid catalog/relation precedence works on the foreground handle, but the four missed manifest paths can still block on a zero-permit executor or mutate Paimon's JVM-global manifest pool.
- Observability and FE/BE propagation: the credential-bearing raw parameter log is removed, the cached scanner metric is safely published, and the paired encoded schema plus serialized processed-table handoff are consistent.
- Data writes and transactions: no data-write/transaction behavior is changed by this PR, and no additional persistence issue was found.
Validation was static only. Per the authoritative bundle, no builds, tests, source changes, or commits were performed.
### What problem does this PR solve? Issue Number: None Related PR: apache#66247 Problem Summary: Paimon read-only system tables and fallback tables hide the file-store handles that actually plan manifests, while snapshot partition loading and row-count collection can plan before ScanNode. An unsafe physical manifest parallelism could therefore bypass the final visible-table check, and early validation could also reject a safe relation-level override. Validate each effective planning handle, preserve the fully merged table during partition projection, and guard row-count plans before they start. ### Release note Paimon manifest parallelism safeguards now cover system-table, fallback-branch, partition-metadata, and statistics planning paths. ### Check List (For Author) - Test: FE checkstyle, Groovy compilation, and manual Paimon 1.3.1 fixture probe passed; unit and P0 regression coverage added but not run locally because the installed third-party toolchain is absent - Behavior changed: Yes. Unsafe hidden manifest-planning handles are rejected before planning while safe relation overrides remain effective. - Does this need documentation: No
|
run buildall |
|
/review |
TPC-H: Total hot run time: 29472 ms |
There was a problem hiding this comment.
Automated review summary
Requesting changes for four substantiated issues at 8ea521522915c65fcbcf1239de94d125d89c0ff9: three P1 correctness/compatibility gaps in legacy STRUCT parsing and effective Paimon wrapper validation, plus one P2 repeated partition-enumeration regression for reader-only OPTIONS.
Critical checkpoint conclusions:
- Goal and proof — The guardrail, precedence, JNI framing, and credential-safe diagnostics goals are coherent and mostly implemented. The added FE/BE/P0 tests are broad, but they do not prove the four reported cases.
- Scope and clarity — Most changes are focused and reuse common helpers. The shared
ColumnTypeparser change unintentionally broadens the compatibility impact beyond Paimon, and the OPTIONS projection path does redundant work. - Concurrency — Detached catalog validation, synchronized publication/reset, double-checked system-table initialization, and volatile/synchronized counter sampling were traced. No lock-order or publication defect remains beyond the independently cached handle lifecycle reported inline.
- Lifecycle — Scanner open/close and catalog reset lifecycles are balanced. The source-table cache and system-wrapper cache can nevertheless represent different generations, which is reported inline.
- Configuration — Reader option ranges and relation > catalog > physical precedence are generally enforced, including CREATE/ALTER/replay paths. Privilege-wrapped fallback and divergent system-wrapper children bypass the intended complete effective-table validation.
- Compatibility — The paired Base64 schema payload is emitted by both V1 and V2 Paimon readers and the encoded protocol is rolling-compatible. The unencoded public parser no longer preserves its prior lowercase STRUCT-key contract.
- Parallel paths — Normal, snapshot, tag, branch, startup, incremental, row-count/statistics, partition, system-table, fallback, V1, and V2 paths were traced. The privilege-wrapped fallback topology is the remaining missed path.
- Conditional checks — New fail-closed checks are generally documented and correctly placed; the direct
instanceof FallbackReadFileStoreTablecondition is insufficient for supported delegated wrappers. - Test coverage — Positive and negative unit/P0 coverage exists for ranges, precedence, lifecycle, framing, fallback, system tables, and row-count planning. Missing coverage corresponds to the four inline findings.
- Test results — The changed expected behavior is internally consistent on inspection. No tests or builds were run because the authoritative review prompt prohibits them.
- Observability — Raw scanner parameters are no longer logged; the derived debug summary and counters are appropriately bounded. No additional logging/metrics issue was found.
- Persistence and transactions — Detached ALTER validation, EditLog publication/replay, restart behavior, and legacy property filtering were traced without a separate persistence defect. No data-write transaction path is changed.
- FE/BE propagation — Both BE reader generations publish the new paired fields and the Java scanner consumes them consistently. The compatibility problem is confined to the shared legacy parser behavior described inline.
- Performance — Reader-only OPTIONS unnecessarily bypass the memoized latest projection and re-enumerate partitions; no other material CPU, allocation, or memory-accounting regression was substantiated.
- Other issues — External catalog input is trusted under the repository threat model; no separate security vulnerability was identified. All other candidates were either fixed in existing live threads or dismissed with concrete code evidence.
There was no additional user-provided review focus, so the whole PR was reviewed. All required second-round normal and risk reviewers converged on this exact four-comment set with NO_NEW_VALUABLE_FINDINGS.
TPC-DS: Total hot run time: 177744 ms |
### What problem does this PR solve? Issue Number: None Related PR: apache#66247 Problem Summary: The unencoded JNI STRUCT parser no longer preserved its historical lowercase field-key contract. Paimon fallback validation also stopped at privilege delegates, system tables could be built from a separately reloaded data handle, and reader-only relation options unnecessarily bypassed the memoized partition projection. Restore legacy parser compatibility, traverse delegated planning handles, construct system wrappers from the exact validated source handle, and keep pure reader tuning on the cached projection. ### Release note Paimon reader tuning avoids redundant partition enumeration, privilege-wrapped fallback tables receive complete manifest validation, and legacy unencoded JNI STRUCT keys retain lowercase compatibility. ### Check List (For Author) - Test: PaimonJniScannerTest (15 passed), targeted legacy parser test, Paimon 1.3.1 privilege-wrapper probe, FE checkstyle, and diff checks passed; FE unit coverage added but not run locally because the installed third-party toolchain is absent - Behavior changed: Yes. System wrappers share the validated source handle and pure reader options reuse memoized metadata. - Does this need documentation: No
There was a problem hiding this comment.
Static review found two blocking Paimon system-table schema consistency defects; both are annotated inline. They are inverse provenance failures: explicit historical OPTIONS lose their selected schema during runtime-safe source reconstruction, while statement-fence-derived reader OPTIONS incorrectly rewind system-table schema binding.
Critical checkpoints:
- Goal, scope, and focus: The PR coherently hardens Paimon reader-option validation, statement snapshot fencing, JNI schema transport, system-wrapper reconstruction, and plugin update validation. It does not fully accomplish the schema-consistency goal because of the two P1 paths. No additional user-provided focus was supplied; the full PR was reviewed.
- Concurrency and lifecycle: Scanner metrics/cached thread sampling, statement caches/reset, catalog ALTER locking, plugin TCCL restoration, wrapper/catalog-loader ownership, and scanner open/close paths were traced. No additional thread-safety, lock-order, lifecycle, or static-initialization defect was found.
- Configuration, compatibility, and parallel paths: Catalog/table/relation/BE option validation, dynamic catalog updates, API gates, V1/V2 encoded schema transport, legacy payloads, special conditions, and ordinary/fallback/delegated/system wrappers were checked. The two system-schema paths are the only remaining correctness gaps.
- Error handling, memory safety, and BE nullable handling: Status/exception boundaries and fail-loud guards were checked; the projection guard converts the first mismatch into a query failure rather than hiding it. No additional ignored-status, ownership/reservation, or ColumnNullable/const defect was found.
- Data correctness, persistence, and writes: The two inline findings are blocking data-read consistency issues. Catalog ALTER candidate validation plus journal/replay otherwise remain consistent; no transactional data-write path is changed.
- FE/BE propagation, performance, and observability: The encoded schema pair and Paimon side-channel options reach both JNI producer/consumer paths; branch-local manifest caps and cached JVM thread sampling are bounded; statistics, debug logs, and error context are adequate. No additional issue was found.
- Tests/results: Changed unit/regression coverage and expected results were inspected and are broad, but they miss the two cross-provenance cases called out inline. Static review only—no builds or tests were run under this review contract.
| public static Table runtimeSafeSystemSource(Table sourceTable, Map<String, String> scanOptions) { | ||
| if (PaimonScanParams.isOptionsPin(scanOptions)) { | ||
| if (sourceTable instanceof FileStoreTable) { | ||
| return PaimonScanParams.applyOptionsWithoutTimeTravel( |
There was a problem hiding this comment.
[P1] Preserve historical schemas for explicit system-table OPTIONS. This branch uses copyWithoutTimeTravel for every marked OPTIONS pin, but a scan handle's systemTableSource is freshly resolved at the latest generation. After old is renamed to new, $ro/$audit_log@options('scan.snapshot-id'='S') binds old from S, then this rebuild exposes the latest row type to planScanInternal; its OPTIONS projection maps old to -1 and aborts before the backend rebuild can restore S. Planning-only OPTIONS do need latest-schema semantics, but explicit selectors need the selected schema. Please retain that provenance/source generation and cover split planning for a historical system view across a rename.
| : pinnedSnapshotId(table, resolved); | ||
| // The statement fence pins data visibility, not schema time travel. Planning-only | ||
| // aliases must retain the latest-schema projection used by the plain relation. | ||
| long schemaId = usesStatementFence || pinnedId < 0 |
There was a problem hiding this comment.
[P1] Propagate this latest-schema sentinel to system-table binding. The normal getTableSchema arm honors schemaId=-1, but its system-table arm bypasses that check and resolveSystemTableAt always applies the marked OPTIONS map; the synthetic scan.snapshot-id=S therefore still rewinds the view's row type. After a schema-only add/rename following S, $ro@options('scan.manifest.parallelism'='1') binds S-era fields while the runtime-safe wrapper keeps the current schema. Please retain/honor the statement-fence provenance in the system path and cover both planning-only and explicit selectors.
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
FE Regression Coverage ReportIncrement line coverage |
TPC-H: Total hot run time: 28663 ms |
TPC-DS: Total hot run time: 169493 ms |
ClickBench: Total hot run time: 23.85 s |
|
run buildall |
|
/review |
TPC-H: Total hot run time: 28741 ms |
TPC-DS: Total hot run time: 170185 ms |
ClickBench: Total hot run time: 23.84 s |
|
Codex automated review failed and did not complete. Error: Review step was failure (possibly timeout or cancelled) Please inspect the workflow logs and rerun the review after the underlying issue is resolved. |
FE UT Coverage ReportIncrement line coverage |
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
FE Regression Coverage ReportIncrement line coverage |
## Summary This backports #66247 to `branch-4.1`. - preserve nested and quoted Paimon field names across the JNI schema bridge - validate and bound Paimon reader options before planning or opening readers - keep per-scan concurrency local instead of resizing shared executors - validate branch, tag, snapshot, system-table, and statistics access consistently - make scanner cleanup retry-safe and add reader thread diagnostics - expand the supported Paimon read-option allowlist ## branch-4.1 adaptations The backport keeps the branch-4.1 JNI constructor and typed partition enumeration APIs. System-table schema serialization also uses the raw, already-associated Paimon table so a safe relation override is not replaced by validation of a physical hidden-table handle. ## Behavior changes Invalid or unsafe reader values now fail early with an actionable error. Supported read options are forwarded consistently, nested quoted field names retain their exact identity, and per-query settings no longer mutate shared process-wide executor sizing. ## Testing - Paimon JNI scanner tests: 15 passed - Targeted FE tests: 97 passed - Branch-specific hidden-table override regression: passed - C++ clang-format check: passed - `git diff --check`: passed
|
PR approved by at least one committer and no changes requested. |
924060929
left a comment
There was a problem hiding this comment.
Reviewed the current head 6a97eb7 with an FE-first focus and rechecked the previously reported paths against the latest code.
The end-to-end design is now coherent: relation options are applied after catalog options without mutating the cached physical table; validation runs on the final effective table; statement-level snapshot fences are shared across plain and option-bearing aliases; system-table, fallback, delegated, statistics, partition, prepared-execution, and deferred BE planning paths preserve the same option/snapshot/schema provenance; and the BE retains rolling-upgrade backstops for payloads from older FEs. The detached ALTER validation and connector classloader/API-major handling also close the catalog initialization race without making legacy images unloadable.
I did not find a new PR-introduced P1/P2 blocker on this head. The earlier hidden system-source runtime-cap and statistics-normalization findings are fixed and covered by targeted tests. Current FE/BE UT, external/P0 regressions, compile, style, and coverage checks are green.
The documented residual snapshot windows for a few Paimon system tables remain worth tracking separately: some Paimon SDK metadata paths ignore scan.snapshot-id, and the two-phase $files path cannot fully bind partition-marker enumeration to the older snapshot. These can cause transient system-table inconsistency during concurrent publication/partition deletion, but they are pre-existing SDK/path limitations, are explicitly outside the advertised OPTIONS capability matrix, and are not regressions introduced by this PR.
From the FE review perspective, this head is ready to merge. Given the size and cross-layer scope of the change, I recommend freezing this PR's scope and handling any further system-table consistency work in follow-up PRs.
## Summary Document the complete user-visible Paimon read behavior implemented by apache/doris#66247 and its branch-4.1 backport apache/doris#66297. - Lists all seven supported bounded batch-read options, their defaults, accepted values, and runtime effects. - Documents relation, Catalog, physical-table, and Paimon-default precedence, including validation of the final effective value. - Explains relation-local aliases, metadata-neutral projection reuse, and the local runtime cap for manifest planning. - Documents atomic Catalog ALTER validation and compatibility behavior for persisted legacy properties. - Covers statement-consistent snapshot/schema binding across partitions, statistics, system tables, and data scans. - Adds the supported Paimon `@options` time-travel selectors, combination constraints, view behavior, and explicit failure semantics. - Lists the system tables that accept `@options` and the unsupported file-creation-time filter. - Documents exact quoted top-level and nested identifier preservation on both Paimon JNI scanner paths. - Records safe logging, the one-second async-reader profile sampling interval, and retry-safe cleanup behavior. The same behavior is documented in current and 4.x English and Chinese pages. Related code changes: - apache/doris#66247 (`master`) - apache/doris#66297 (`branch-4.1`) ## Version scope The implementation targets Doris master and branch-4.1, so this change updates `current` and `4.x`. The behavior is not present in 3.x or 2.1. ## Validation - `yarn docs:links:changed` - `yarn docs:features:changed` - `yarn docs:i18n-sync:changed` - `yarn docs:lint:changed` - `yarn build` (all configured English, Chinese, Japanese, and historical-version pages; exit code 0) - `git diff --check` All validation commands pass. The reports retain existing repository-wide Markdown, sidebar, SEO, external-link, and Japanese translation-candidate notices; no new error is introduced by these changes. ## Versions - [x] dev - [x] 4.x - [ ] 3.x (feature not supported) - [ ] 2.1 or older (feature not supported) ## Languages - [x] Chinese - [x] English - [x] Japanese candidate translation needed ## Docs Checklist - [x] Checked by AI - [ ] Test Cases Built - [x] Updated required version and language counterparts, or explained why not - [x] If only one language changed, confirmed whether source/translation counterparts need sync
What problem does this PR solve?
Issue Number: None
Related PR: None
Problem Summary:
The Paimon JNI read path had several correctness and operational guardrail gaps:
read.batch-sizeaccepted zero, negative, or excessively large values. In particular, zero can make the vectorized reader return without advancing input.scan.manifest.parallelism=0can block on a zero-permit semaphore, while a value above the CPU-sized default causes Paimon to replace a JVM-static executor and leaves the new pool visible to later queries.`region,code`was decoded as two fields, and nested STRUCT child names containing#,,, or:also collided with the type grammar.enable_file_scanner_v2=falsedid not emit the safe schema payload used by FileScannerV2.paimon.table-option.*accepted options which can select a different table context or affect writes after Doris has already bound the original schema.ThreadInfo[], although the Paimon async-reader pool is JVM-global.table@options(...)relation.How does this PR solve it?
read.batch-size:1..65536file-reader-async-threshold:1 MB..1 GBfile-index.read.enabled: Booleansource.split.target-size: positive memory sizesource.split.open-file-cost: non-negative memory sizescan.manifest.parallelism:1..Runtime.availableProcessors()scan.plan-sort-partition: Booleanrelation @options> Doris catalog option > physical table option > Paimon default.read.batch-size=0orscan.manifest.parallelism=0from bypassing Doris-side safeguards.1..Runtime.availableProcessors(), preserving the JVM-global executor-capacity invariant.required_fields_base64andcolumns_types_base64schema payloads from both the legacy and V2 C++ readers. Every complete list item is independently encoded, and every nested STRUCT child name is encoded inside the type descriptor.required_fieldsandcolumns_typesparameters as a compatibility fallback. The Java scanner accepts only a complete encoded pair, so it cannot combine two framing versions accidentally.CatalogPropertybefore the live catalog is changed; connectors without this capability retain the existing tentative-validation path and rollback behavior.paimon.table-option.*entries. The raw persisted property is retained so image/edit-log compatibility is not destructive.For example, the following nested schema is now transported without colliding with either the outer list framing or the STRUCT grammar:
Example query-level tuning:
Two aliases of the same table may use different values in the same statement because each relation receives its own
Table.copy(...):Thread statistics microbenchmark
Dataset and method:
getAllThreadIds()andgetThreadInfo(ids, 0), then scans the returnedThreadInfo[].ThreadMXBean. A checksum blackhole consumes every returned count.This microbenchmark isolates statistics collection rather than scan I/O. It shows that the old cost grows with JVM thread count, while cache hits avoid both the full thread walk and its per-call allocation. The tradeoff is that this profile gauge can be up to one second stale; it does not affect query execution or scheduling.
Tests
Passed locally:
PaimonJniScannerTest: 15 tests, 0 failures, Maven build cache disabled.Added coverage:
Not run locally:
protocincluded). CI buildall and regression checks are requested on this PR.Release note
Paimon catalogs and relation
@optionsnow support seven bounded batch-read controls:read.batch-size,file-reader-async-threshold,file-index.read.enabled,source.split.target-size,source.split.open-file-cost,scan.manifest.parallelism, andscan.plan-sort-partition. Unsafe catalog, physical-table, and manifest-parallelism settings are rejected. Both Paimon scanner routes support quoted top-level and nested identifiers containing delimiter characters. Scanner DEBUG logs no longer include raw parameters, failed Paimon catalog validation is atomic, persisted legacy options remain loadable without being applied, and scanner statistics reuse a short-lived JVM-wide thread-count sample.Check List (For Author)
Review follow-up
The review fixes make empty identifiers and option precedence explicit:
$marker. Therefore an empty projection is encoded as the empty payload, while one empty field name is encoded as$; both the legacy and V2 C++ producers use this shared encoding.read.batch-size=0plus catalog1024, or plus relation@options(...=4096), is accepted with the safe final value; the same physical table without an override is still rejected. The same rule applies to manifest parallelism.{}versus{\"\"}unit coverage, scanner constructor coverage, final-boundary/no-override coverage, safe catalog/relation override coverage, and P0 queries through both scanner routes.PaimonJniScannerTestnow runs 15 tests with no failures. A direct Paimon 1.3.1 runtime probe also accepted the safe relation override and rejected the unsafe final value.Review follow-up: hidden planning handles
This update closes the four remaining pre-ScanNode planning gaps:
$partitionsexposes an empty option map while its private data table performs manifest planning. Doris now applies and validates relation options on that hidden data table, while type inspection remains non-planning so a safe override is not rejected prematurely.FallbackReadFileStoreTableis validated recursively because its main and fallback children plan independently.scan.manifest.parallelism=0is rejected before enumeration, while@options('scan.manifest.parallelism'='1')is preserved instead of being lost through a raw catalog reload.fetchRowCount()validates immediately beforenewScan().plan(); coverage exercises bothExternalRowCountCacheand manual analysis entry points.For example, given a partitioned table whose physical option is unsafe:
Added tests use real Paimon 1.3.1
PartitionsTable,FallbackReadFileStoreTable, and file-store table objects, plus a partitioned P0 fixture. FE checkstyle, Groovy compilation, and isolated Paimon fixture probes pass locally. Full FE unit tests and the external P0 environment remain delegated to CI because this checkout does not contain the installed third-party toolchain, includingprotoc.Review follow-up: parser compatibility and wrapper identity
This update addresses four compatibility and planning-identity findings:
struct<Mixed:int>produces the historical keymixed; only the versioned Base64 Paimon grammar preservesMixed.DelegatedFileStoreTable.wrapped()handle as well as the fallback child. Therefore aPrivilegedFileStoreTable(FallbackReadFileStoreTable(...))cannot hide an unsafe fallback manifest executor.SystemTableLoaderdirectly from the same cachedFileStoreTablethat Doris validates. The catalog is no longer called a second time, so a refreshed physical handle cannot be planned while an older handle is validated.read.batch-size,file-reader-async-threshold,file-index.read.enabled,source.split.target-size, orsource.split.open-file-cost) validate their effective table and then reuse the memoized latest snapshot projection. Snapshot-selecting and manifest/partition-order planning options retain the effective-handle projection path.The partitioned counting test verifies that reader-only tuning performs zero direct projection loads, while the existing manifest-override test verifies that safety-sensitive options still load from the effective copy.
Validation for this update:
[Mixed, UPPER]before the fix and GREEN output[mixed, upper]after it.PaimonJniScannerTest: 15 passed, confirming encoded nested names still preserve their exact spelling.Full FE unit execution remains delegated to CI because the checkout does not contain the installed third-party toolchain, including
protoc.Review follow-up: late serialization and connector-scoped schema framing
This update closes the four findings from the latest review:
For example, this composition now reuses the cached partition projection and validates the safe final scan handle:
Validation for this update:
PaimonJniScannerTest: 15 passed.protoc, is absent; CI buildall and review were requested after the push.Follow-up: complete safe batch-read options and BE UT compilation
This update expands the dynamic allowlist from two JNI-reader knobs to all seven safe batch-read controls consumed by the Doris Paimon 1.3.1 scan path:
read.batch-size1..65536file-reader-async-threshold1 MB..1 GBfile-index.read.enabledsource.split.target-sizesource.split.open-file-costscan.manifest.parallelism1..Runtime.availableProcessors()scan.plan-sort-partitionThe keys deliberately retain their official Paimon names. For example,
read.batch-sizemust not becomescan.read.batch-size:CoreOptions.READ_BATCH_SIZEreads the former key, while split controls belong to Paimon'ssource.*namespace and only manifest/partition planning controls usescan.*.Catalog defaults and relation overrides accept the same list:
CREATE CATALOG paimon_hms PROPERTIES ( "type" = "paimon", "paimon.catalog.type" = "hms", "paimon.table-option.source.split.target-size" = "64 MB", "paimon.table-option.file-index.read.enabled" = "true" ); SELECT * FROM paimon_table@options( 'source.split.target-size' = '32 MB', 'file-index.read.enabled' = 'false');The existing precedence remains
relation @options > Doris catalog > physical table > Paimon default. Relation-local split and reader settings can reuse the memoized partition projection because they do not select another snapshot; manifest parallelism and partition sorting keep an effective relation projection because they affect metadata planning.The allowlist still excludes table-context selectors from Catalog defaults,
scan.max-splits-per-taskbecause it is consumed by Paimon's Flink source enumerator rather than Doris batch planning, and all streaming, storage-layout, write, and compaction settings. Snapshot/tag/startup selection remains available through the dedicated relation@optionspath.The same commit fixes the BE UT compilation failure caused by two test-only
JniColumndesignated initializers omitting the newly addedoutput_typemember. Both aggregates now initialize it explicitly, preserving Clang's warnings-as-errors invariant.Validation for this update:
protoc.output_typedesignated-initializer diagnostics. The complete UT suite is still running.