Repository navigation
[fix](point query) Fix BE crash when a point query reads a column added by light schema change - #68997
Conversation
…UCT column added by light schema change ### What problem does this PR solve? Issue Number: close #xxx Related PR: apache#68198 Problem Summary: A light schema change adds a column without writing any data, so until the next load the BE's tablet schema does not have it. A short-circuit point query that reads such a column from the column store (the column is outside `row_store_columns`) builds the column from the query slot. apache#68198 built it with `variant_util::get_column_by_type`, which is meant for variant subcolumns and has no branch for MAP or STRUCT. It throws, and `tablet_fetch_data` does not catch exceptions the way the other RPCs do, so the BE aborts: terminate called after throwing an instance of 'doris::Exception' what(): [E6] unexcepted data column type: Map(Nullable(String), Nullable(Array(Nullable(INT)))), column name is: obj Reproduce on a merge-on-write table with "store_row_column" = "true" and "row_store_columns" = "k,stored": INSERT INTO t VALUES (1, 10, 100); ALTER TABLE t ADD COLUMN obj MAP<STRING, ARRAY<INT>> NULL; -- wait until FINISHED SET enable_short_circuit_query = true; SET enable_short_circuit_query_access_column_store = true; SELECT obj, stored, wide FROM t WHERE k = 1; Before: the BE aborts and the client gets `RpcException ... UNAVAILABLE: io exception`. After: `NULL 10 100`, the same as a normal scan. The fix: 1. Add `ReadSchema::tablet_column_from_slot`, which builds the TabletColumn a slot reads from the slot's name, unique id, type and default value. It covers every type the slot can carry; ARRAY, MAP and STRUCT get their sub columns, named the way FE names them (item / key / value / field name). The point query uses it instead of `variant_util::get_column_by_type`. 2. `_tablet_fetch_data` turns an exception into an error status, so a point query that throws fails instead of taking the BE down. ### Release note Fix BE crash when a short-circuit point query reads a MAP or STRUCT column that a light schema change added before any new data was loaded. ### Check List (For Author) - Test: Regression test / Unit Test / Manual test - Regression test: point_query_p0/test_point_query_light_schema_change now also adds MAP, STRUCT and ARRAY columns. It passes with the fix; without it the BE aborts at the new `added_complex_columns` query. All 17 point_query_p0 suites pass with the fix. - Unit Test: 3 new ReadSchemaTest cases for tablet_column_from_slot. - Manual test: the SQL above on an ASAN build, before and after the fix. For 2, a build that still uses the old column builder returns the error to the client and the BE keeps running. - Behavior changed: No - Does this need documentation: No Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
/review |
There was a problem hiding this comment.
Completed static review of all seven changed files at commit 6dca50d. No new actionable findings and no existing P0/P1 inline findings to carry forward. The change reconstructs the declared type of a column added by light schema change so a point lookup before the next load can use the segment's default iterator, including MAP/STRUCT/ARRAY, while converting Doris exceptions to an RPC error status.
Critical checkpoint conclusions:
- Goal and proof: FE slot -> recursive TabletColumn reconstruction -> missing segment UID -> default iterator implements the intended pre-first-load behavior by inspection. Added unit and regression tests exercise the conversion and complex-column reads; execution was not performed.
- Scope and reuse: the seven-file change is focused; one caller uses a shared ReadSchema helper and existing type/field-length utilities.
- Concurrency and locks: independent RPC callbacks build request-local metadata. Tablet schema snapshots retain shared ownership under the existing metadata lock, and the reusable block pool retains its mutex. No new shared mutation, lock order or heavy locked operation was introduced.
- Lifecycle and static initialization: children have owned storage without ownership cycles. Failed initialization does not publish a partial Reusable; failed lookup destroys its partial block rather than pooling it. Scoped COW restoration and rowset/cache RAII preserve cleanup. No new production global initializer exists.
- Configuration: no new setting; the existing column-store access flag keeps its gate.
- Compatibility and rolling upgrades: existing FE slot metadata is consumed without wire or persisted-format changes. No new runtime library, linker or glibc API dependency was introduced; binary compatibility was not tested.
- Thrift/protobuf IDs: no gensrc definitions changed, so release-branch field-ID comparisons are inapplicable.
- Parallel paths: inspected schema-present/absent columns, full/partial row-store, cloud/local segment reads and the separate VARIANT access path. Existing paths retain their behavior; current FE short-circuit eligibility excludes VARIANT tables.
- Conditions and error handling: the absent-column condition has the concrete pre-load schema-gap cause documented at the caller. Non-OK Status remains propagated; both catch boundaries convert Doris exceptions. FE checks response status before accepting any batch. Nullability and typed defaults follow the existing iterator.
- Test coverage: three helper tests cover recursive children, scalar/complex round trips, string lengths, DECIMALV2 declaration details and VARIANT parameters. Regression additions cover MAP/STRUCT/ARRAY before load, old rows after load and populated new rows. Dedicated exception-injection, concurrency, prepared-cache and cloud tests are absent; no concrete new defect was substantiated from those gaps.
- Changed results: every added golden value agrees with the SQL by inspection. Each new query selects one full unique key, so row order is deterministic. Output generation provenance was not independently verified and outputs were not regenerated.
- Observability: existing column-identifying errors and point-query timing/profile remain sufficient for this local conversion; no new distributed operation or background state needs instrumentation.
- Transactions and persistence: no production metadata writes, EditLog, publish or failover path changed.
- Writes and atomicity: production write behavior is unchanged; a failed lookup returns an error and FE does not consume a partial batch.
- FE/BE variables: no new transmitted field; name, unique ID, full nested type/nullability and default use the existing descriptor path. Prepared query context invalidation on schema version change remains in place.
- Performance: reconstruction is linear in the type tree and limited to columns absent from the tablet schema. Missing-UID default reads add no data-column page IO. No new scan, large buffer or lock contention was identified.
- Other invariants and BE hygiene: rowset/version selection, MoW delete bitmap and physical segment IDs are unchanged. The text-only build-hygiene command passed header layering/closure/reach/PCH, extern-template pairing and unity-skip coverage. No builds, unit/regression tests, formatting mutation or source changes were performed.
No additional user focus was supplied. Initial risks covering nested type fidelity, default metadata and exception cleanup were independently investigated and dismissed with code evidence. Two normal reviewers and a separate risk reviewer all returned NO_NEW_VALUABLE_FINDINGS in round 1; the main reconciliation and final changed-file/unresolved-point sweep found no unresolved candidate. Review complete.
|
run buildall |
TPC-H: Total hot run time: 29066 ms |
TPC-DS: Total hot run time: 152764 ms |
ClickBench: Total hot run time: 24.64 s |
|
PR approved by anyone and no changes requested. |
1 similar comment
|
PR approved by anyone and no changes requested. |
|
PR approved by at least one committer and no changes requested. |
1 similar comment
|
PR approved by at least one committer and no changes requested. |
What problem does this PR solve?
Since #68198, a short-circuit point query that reads a MAP or STRUCT column added by light schema change, before any new load, aborts the BE.
tablet_fetch_datanow also catches exceptions, so a point query that throws returns an error instead.Issue Number: close #xxx
Related PR: #xxx
Problem Summary:
Release note
None
Check List (For Author)
Test
Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)