|
1 | 1 | #include <Storages/MergeTree/AlterConversions.h> |
2 | 2 | #include <Storages/MergeTree/LoadedMergeTreeDataPartInfoForReader.h> |
3 | 3 | #include <Storages/MergeTree/MergeTreeRangeReader.h> |
| 4 | +#include <Storages/MergeTree/MergeTreeVirtualColumns.h> |
4 | 5 | #include <Storages/MutationCommands.h> |
5 | 6 | #include <Interpreters/MutationsInterpreter.h> |
6 | 7 | #include <Interpreters/MutationsNonDeterministicHelpers.h> |
7 | 8 | #include <Parsers/ASTAlterQuery.h> |
8 | 9 | #include <Parsers/ASTAssignment.h> |
| 10 | +#include <Parsers/ASTLiteral.h> |
9 | 11 | #include <Common/ProfileEvents.h> |
10 | 12 | #include <ranges> |
11 | 13 |
|
@@ -64,6 +66,41 @@ static MutationCommand createCommandWithUpdatedColumns( |
64 | 66 | return res; |
65 | 67 | } |
66 | 68 |
|
| 69 | +static bool isLightweightDeleteCommand(const String & column_name, const ASTPtr & ast) |
| 70 | +{ |
| 71 | + if (column_name != RowExistsColumn::name) |
| 72 | + return false; |
| 73 | + |
| 74 | + const auto * literal = ast->as<ASTLiteral>(); |
| 75 | + if (!literal) |
| 76 | + return false; |
| 77 | + |
| 78 | + if (literal->value.getType() != Field::Types::UInt64) |
| 79 | + return false; |
| 80 | + |
| 81 | + return literal->value.safeGet<UInt64>() == 0; |
| 82 | +} |
| 83 | + |
| 84 | +static MutationCommand createLightweightDeleteCommand(const MutationCommand & command) |
| 85 | +{ |
| 86 | + chassert(command.type == MutationCommand::Type::UPDATE); |
| 87 | + chassert(command.predicate != nullptr); |
| 88 | + |
| 89 | + auto alter_command = std::make_shared<ASTAlterCommand>(); |
| 90 | + alter_command->type = ASTAlterCommand::DELETE; |
| 91 | + |
| 92 | + if (command.partition) |
| 93 | + alter_command->partition = alter_command->children.emplace_back(command.partition->clone()).get(); |
| 94 | + |
| 95 | + alter_command->predicate = alter_command->children.emplace_back(command.predicate->clone()).get(); |
| 96 | + auto mutation_command = MutationCommand::parse(alter_command.get()); |
| 97 | + |
| 98 | + if (!mutation_command) |
| 99 | + throw Exception(ErrorCodes::LOGICAL_ERROR, "Failed to parse command {}", alter_command->formatForErrorMessage()); |
| 100 | + |
| 101 | + return *mutation_command; |
| 102 | +} |
| 103 | + |
67 | 104 | AlterConversions::AlterConversions( |
68 | 105 | const MutationCommands & mutation_commands_, |
69 | 106 | const ContextPtr & context) |
@@ -308,16 +345,29 @@ MutationCommands AlterConversions::filterMutationCommands(Names & read_columns, |
308 | 345 | } |
309 | 346 | else if (command.type == MutationCommand::Type::UPDATE) |
310 | 347 | { |
| 348 | + bool has_lightweight_delete = false; |
311 | 349 | std::unordered_map<String, ASTPtr> new_updated_columns; |
| 350 | + |
312 | 351 | for (const auto & [column, ast] : command.column_to_update_expression) |
313 | 352 | { |
314 | | - if (read_columns_set.contains(column)) |
| 353 | + if (isLightweightDeleteCommand(column, ast)) |
| 354 | + { |
| 355 | + has_lightweight_delete = true; |
| 356 | + } |
| 357 | + else if (read_columns_set.contains(column)) |
315 | 358 | { |
316 | 359 | ast->collectIdentifierNames(source_columns); |
317 | 360 | new_updated_columns.emplace(column, ast->clone()); |
318 | 361 | } |
319 | 362 | } |
320 | 363 |
|
| 364 | + if (has_lightweight_delete) |
| 365 | + { |
| 366 | + auto new_command = createLightweightDeleteCommand(command); |
| 367 | + new_command.predicate->collectIdentifierNames(source_columns); |
| 368 | + filtered_commands.push_back(std::move(new_command)); |
| 369 | + } |
| 370 | + |
321 | 371 | if (!new_updated_columns.empty()) |
322 | 372 | { |
323 | 373 | auto new_command = createCommandWithUpdatedColumns(command, std::move(new_updated_columns)); |
|
0 commit comments