Repository navigation
Conversation
Issue Number: None Root cause: validation could mutate shared complex column trees through const_cast when adapting nested values. Fix: propagate ColumnPtr ownership references through recursive validation and use targeted copy-on-write before mutation. Testing: BE build, manual MAP reuse reproduction, and datatype_p0/map/test_map_insert_shared_column regression test.
|
/review |
|
Codex automated review failed and did not complete. Error: Review setup stopped before context preparation ran; inspect the first failed or cancelled setup step. Please inspect the workflow logs and rerun the review after the underlying issue is resolved. |
|
Potential performance regression: validation can clone columns that are already exclusively owned. The shared-column isolation is needed for correctness, but the new helper introduces two extra owners before the COW decision in ColumnPtr real_column_ptr =
column_ptr == nullptr ? column : column_ptr->get_nested_column_ptr();
// Inside mutate_column():
auto mutable_column = IColumn::mutate(column);For an initially exclusive, non-nullable column, the reference count is 1 in the owning slot, 2 after constructing static MutablePtr mutate(Ptr ptr) {
MutablePtr res = ptr->shallow_mutate(); // Clone decision happens here.
ptr.reset(); // Too late to avoid that clone.
res->mutate_subcolumns();
return res;
}For nullable columns, the local alias additionally retains the nested column while the by-value parameter retains the wrapper. Also, This can add column-data copying, allocation, memory bandwidth use, and peak memory, especially for large or deeply nested complex columns. Copying the smart pointers only increments reference counts; the subsequent COW calls cause the column clones. Suggested changes:
Please add ownership/allocation coverage alongside the SQL correctness regression: exclusive columns and descendants should be reused when possible; shared outputs must remain isolated during string truncation; nested ARRAY/MAP/STRUCT inputs should not repeatedly clone the same already-detached payload. Validation: traced the COW implementation and reproduced the extra-clone pattern in an isolated model using its reference-counting implementation. This is not a full BE benchmark, so no SQL slowdown or speedup percentage is claimed. |
### Background Tablet write validation can truncate strings, round legacy decimals, and deduplicate map keys. Expression outputs can share column trees, so validation must preserve copy-on-write ownership before changing them. ### What problem does this PR solve? Issue Number: None Related PR: None PR Type: Bugfix Problem Summary: Writing a shared complex column can modify another output column or leave stale views after replacing a nested string. Extract tablet validation into a standalone dispatcher that consumes and returns a column, detaches shared nodes once, and recursively validates writable child slots. Add ownership and nested-value tests; preserve historical DecimalV2 precision/scale behavior. ### Details - **Change map:** About 550 lines of production code replace the converter's embedded validator; about 530 lines of unit/regression tests plus generated regression output. The validator separates scalar checks, nullable handling, and Array/Map/Struct traversal; the converter retains block-level orchestration. - **Frequency:** When writable validation encounters shared column storage, including one map expression reused by multiple output columns. - **Root cause:** Mutable access through const casts bypassed COW; nested replacement could invalidate cached column views. Temporary owning pointers can also cause unnecessary cloning. - **Why existing tests missed it:** They did not check shared outputs together with nested replacement or verify unique column storage addresses and reference counts. - **Fix:** Consume the input owner, perform COW once at the public boundary, and borrow mutable child slots during recursion. Propagate inherited NULLs and original-row mappings. Deduplicate each map once when visited. - **Other paths and branches:** The common tablet converter covers cloud and shared-nothing writes. Automatic picks to 4.1 and 4.2 conflict in `vtablet_block_convertor.cpp`; no release pick is requested. - **Behavior change:** Shared source columns remain unchanged during validation. Nested nullable validation preserves outer-row filtering. DecimalV2 retains its historical execution precision/scale (27, 9); declared-schema enforcement and map-key collisions caused by string truncation remain outside this fix. ### Testing On the development machine: - `BUILD_TYPE=ASAN sh build.sh --be -j48`: passed for the final revision. - `BUILD_TYPE_UT=ASAN sh run-be-ut.sh --run --filter='TabletColumnValidatorTest.*:ColumnNullableTest.*:ColumnArrayTest.*:ColumnStructTest.*:ColumnMapTest.*' -j48`: 107 tests passed, including all 22 new validator tests. - Repository clang-format 16 scripts, build hygiene, `git diff --check`, and clang-tidy on both changed source TUs and the new UT: passed. - The existing shared-map regression and generated output are retained; that regression was not rerun after this refactoring. ### Release note Fix incorrect results or failures when inserting shared complex columns that require tablet validation. ### Check List (For Author) - Behavior changed: Yes (see Details) - Does this need documentation: No - Pre-submission status: Partially verified: ASAN build and focused/related UTs passed; end-to-end regression not rerun after refactoring. ### AI Disclosure - Tool: Codex (GPT-6). - Generated: Code, tests, and this description. - Human review: The author reviewed the design and an earlier source version; the final changes remain available for review.
### Background Tablet write validation can truncate strings, round legacy decimals, and deduplicate map keys. Expression outputs can share column trees, so validation must preserve copy-on-write ownership before changing them. ### What problem does this PR solve? Issue Number: None Related PR: apache#70421 (superseded) PR Type: Refactor Problem Summary: Tablet validation is embedded in the block converter as a large recursive function that mixes type dispatch, nullable handling, row filtering, and mutation. Extract it into a standalone, testable column validator with per-type helpers and a shared validation context. The new entry reads an immutable input tree and returns a validated column. Scalar checks reuse input storage; complex types build new shells around validated children, avoiding shared-column corruption and full-buffer copies for read-only validation. ### Details - **Change map:** Roughly 500 lines of embedded validation are replaced by a standalone implementation and interface; the converter keeps block orchestration. Add ownership/validation UTs and a 55-line regression with generated output. No new column mutation accessor is needed. - **Moves vs. logic changes:** Move scalar checks and decimal bound caches into per-type helpers/context. Centralize physical nullable handling and original-row mapping. Replace const-cast mutation with immutable recursive traversal and fresh container shells. String truncation returns a replacement; DecimalV2 clones only if rounding is needed. Each new map shell deduplicates once, detaching child data only when filtering duplicates. - **Behavior change:** Validation no longer modifies shared source columns or retains stale views after nested string replacement. Inherited NULLs skip nested payload checks and rejected elements filter their original outer row. - **Compatibility:** No wire or storage format changes. DecimalV2 keeps historical execution precision/scale (27, 9); enforcing declared schema parameters and resolving map-key collisions after string truncation remain outside this change. This refactoring targets master without release pick requests. - **Performance impact:** Read-only scalar columns and unchanged leaf buffers remain shared, including offsets and null maps. Complex types allocate new shells even when their children are unchanged; this trades small container allocations for simple ownership without recursive detachment. UTs verify storage reuse and source isolation. No throughput benchmark was run. - **Rollback:** Revert this commit; no metadata or data migration is needed. ### Testing - `BUILD_TYPE_UT=ASAN sh run-be-ut.sh --run --filter='TabletColumnValidatorTest.*' -j48`: 24 tests passed on the development machine. Covers shared read-only leaves, nested shell construction, replacement/source isolation, map deduplication, NULL propagation and decimal compatibility. - Repository clang-format 16 scripts, build hygiene, `git diff --check`, and prescribed clang-tidy on the changed source TUs and validator UT: passed. - No standalone BE build or end-to-end regression was rerun for this revision. The ASAN UT script compiled the affected production code and test binary; the existing shared-map regression and generated output are retained. ### Release note Fix incorrect results or failures when inserting shared complex columns that require tablet validation. ### Check List (For Author) - Behavior changed: Yes (see Details) - Does this need documentation: No - Pre-submission status: Partially verified: focused ASAN UTs and static checks passed; standalone BE build and end-to-end regression not rerun after this change. ### AI Disclosure - Tool: Codex (GPT-6). - Generated: Code, tests, and this description. - Human review: The author reviewed the design and an earlier source version; the final changes remain available for review.
Background
Tablet write validation can truncate strings, round legacy decimals, and deduplicate map keys. Expression outputs can share column trees, so validation must preserve copy-on-write ownership before changing them.
What problem does this PR solve?
Issue Number: None
Related PR: None
PR Type: Bugfix
Problem Summary:
Writing a shared complex column can modify another output column or leave stale views after replacing a nested string. Extract tablet validation into a standalone dispatcher that consumes and returns a column, detaches shared nodes once, and recursively validates writable child slots. Add ownership and nested-value tests; preserve historical DecimalV2 precision/scale behavior.
Details
vtablet_block_convertor.cpp; no release pick is requested.Testing
On the development machine:
BUILD_TYPE=ASAN sh build.sh --be -j48: passed for the final revision.BUILD_TYPE_UT=ASAN sh run-be-ut.sh --run --filter='TabletColumnValidatorTest.*:ColumnNullableTest.*:ColumnArrayTest.*:ColumnStructTest.*:ColumnMapTest.*' -j48: 107 tests passed, including all 22 new validator tests.git diff --check, and clang-tidy on both changed source TUs and the new UT: passed.Release note
Fix incorrect results or failures when inserting shared complex columns that require tablet validation.
Check List (For Author)
AI Disclosure