-
Notifications
You must be signed in to change notification settings - Fork 3.9k
[fix](be) Validate WAL replay column types #66230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,13 +99,42 @@ Status WalReader::_do_get_next_block(Block* block, size_t* read_rows, bool* eof) | |
| return Status::InternalError("read wal {} fail, pos {}, columns size {}", _wal_path, | ||
| pos, src_block.columns()); | ||
| } | ||
| ColumnPtr column_ptr = src_block.get_by_position(pos).column; | ||
| if (!column_ptr && slot_desc->is_nullable()) { | ||
| column_ptr = make_nullable(column_ptr); | ||
| const auto& source_column = src_block.get_by_position(pos); | ||
| const auto& target_column = output_block_columns[index]; | ||
| auto source_status = source_column.check_type_and_column_match(); | ||
| if (!source_status.ok()) { | ||
| return Status::InternalError( | ||
| "Invalid WAL column while replaying WAL {}: slot={} (unique_id={}), " | ||
| "source_position={}, error={}", | ||
| _wal_path, slot_desc->col_name(), slot_desc->col_unique_id(), pos, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Roll back the replay transaction before requeueing this error These new mismatch returns propagate through the fragment future, but |
||
| source_status.to_string()); | ||
| } | ||
| dst_block.insert(index, ColumnWithTypeAndName(std::move(column_ptr), | ||
| output_block_columns[index].type, | ||
| output_block_columns[index].name)); | ||
|
|
||
| ColumnWithTypeAndName replay_column(source_column.column, target_column.type, | ||
| target_column.name); | ||
|
Comment on lines
+102
to
+114
|
||
| auto replay_status = replay_column.check_type_and_column_match(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Preserve the serialized source type through compatible schema changes This target-type validation rejects retained-ID schema changes before the load scanner can cast them. For example, a light
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Validate the complete AGG_STATE signature and storage layout This compatibility check is too weak for |
||
| if (!replay_status.ok()) { | ||
| return Status::InternalError( | ||
| "WAL replay column type mismatch: wal={}, slot={} (unique_id={}), " | ||
| "source_position={}, source_name={}, source_type={}, source_column={}, " | ||
| "target_name={}, target_type={}, error={}", | ||
| _wal_path, slot_desc->col_name(), slot_desc->col_unique_id(), pos, | ||
| source_column.name, source_column.type->get_name(), | ||
| source_column.column->get_name(), target_column.name, | ||
| target_column.type == nullptr ? "null" : target_column.type->get_name(), | ||
| replay_status.to_string()); | ||
| } | ||
|
Comment on lines
+116
to
+126
|
||
| if (!source_column.type->equals(*target_column.type)) { | ||
| return Status::InternalError( | ||
| "WAL replay logical type mismatch: wal={}, slot={} (unique_id={}), " | ||
| "source_position={}, source_name={}, source_type={}, target_name={}, " | ||
| "target_type={}", | ||
| _wal_path, slot_desc->col_name(), slot_desc->col_unique_id(), pos, | ||
| source_column.name, source_column.type->get_name(), target_column.name, | ||
| target_column.type->get_name()); | ||
| } | ||
|
Comment on lines
+127
to
+135
|
||
| dst_block.insert(index, ColumnWithTypeAndName(source_column.column, target_column.type, | ||
| target_column.name)); | ||
| index++; | ||
| } | ||
| block->swap(dst_block); | ||
|
|
@@ -142,4 +171,4 @@ Status WalReader::_get_columns_impl(std::unordered_map<std::string, DataTypePtr> | |
| return Status::OK(); | ||
| } | ||
|
|
||
| } // namespace doris | ||
| } // namespace doris | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P2] Add executable coverage for the mismatch-and-retry path
This changes a kernel replay path to replace a fatal projection cast with compatibility checks and retryable statuses, but the PR adds no test for that behavior. The helper test only checks hand-built columns, the WAL writer/reader test round-trips matching types, and the only legacy scanner tests are disabled/count-only. Please add enabled serialized-WAL coverage that distinguishes a supported promotion (which should reach the existing CAST) from a genuinely incompatible mapping and
AGG_STATEsignature/layout (which should return a contextual error), and verify authenticated rollback, WAL retention/retry, and wait-mode exhaustion signaling after a fragment failure.