| 5044 | } |
| 5045 | |
| 5046 | void MergeTreeData::checkMutationIsPossible(const MutationCommands & commands, const Settings & /*settings*/) const |
| 5047 | { |
| 5048 | for (const auto & disk : getDisks()) |
| 5049 | if (!disk->supportsHardLinks()) |
| 5050 | throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "Mutations are not supported for immutable disk '{}'", disk->getName()); |
| 5051 | |
| 5052 | /// Reject mutations that bypass UK dedup: DELETE/UPDATE rewrite rows; |
| 5053 | /// MATERIALIZE COLUMN / CLEAR COLUMN (the latter serialized as |
| 5054 | /// `DROP_COLUMN` with `clear=true`) rewrite stored bytes. |
| 5055 | if (auto uk_metadata = getInMemoryMetadataPtr(getContext(), false); uk_metadata->hasUniqueKey()) |
| 5056 | { |
| 5057 | const auto & uk_column_names = uk_metadata->getUniqueKeyColumns(); |
| 5058 | auto is_uk_column = [&](const String & column) |
| 5059 | { |
| 5060 | return std::find(uk_column_names.begin(), uk_column_names.end(), column) != uk_column_names.end(); |
| 5061 | }; |
| 5062 | |
| 5063 | for (const auto & command : commands) |
| 5064 | { |
| 5065 | if (command.type == MutationCommand::DELETE || command.type == MutationCommand::UPDATE) |
| 5066 | throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, |
| 5067 | "ALTER DELETE / ALTER UPDATE is not supported on tables with UNIQUE KEY"); |
| 5068 | |
| 5069 | /// MATERIALIZE TTL rewrites parts to apply expiration, bypassing the UNIQUE KEY |
| 5070 | /// dedup path (like MATERIALIZE COLUMN below) — and TTL is unsupported anyway |
| 5071 | /// while merges are disabled. Reject so an ATTACH-loaded UK+TTL table cannot |
| 5072 | /// materialize it. |
| 5073 | if (command.type == MutationCommand::MATERIALIZE_TTL) |
| 5074 | throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, |
| 5075 | "ALTER TABLE ... MATERIALIZE TTL is not supported on tables with UNIQUE KEY"); |
| 5076 | |
| 5077 | if (command.type == MutationCommand::MATERIALIZE_COLUMN && is_uk_column(command.column_name)) |
| 5078 | throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, |
| 5079 | "ALTER TABLE ... MATERIALIZE COLUMN `{}` is not supported: the column is part of the UNIQUE KEY, " |
| 5080 | "and MATERIALIZE would rewrite stored values without going through UNIQUE KEY dedup, " |
| 5081 | "producing duplicate live keys. UNIQUE KEY columns: ({}).", |
| 5082 | command.column_name, fmt::join(uk_column_names, ", ")); |
| 5083 | |
| 5084 | if (command.type == MutationCommand::DROP_COLUMN && command.clear && is_uk_column(command.column_name)) |
| 5085 | throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, |
| 5086 | "ALTER TABLE ... CLEAR COLUMN `{}` is not supported: the column is part of the UNIQUE KEY, " |
| 5087 | "and CLEAR would rewrite stored values without going through UNIQUE KEY dedup, " |
| 5088 | "producing duplicate live keys. UNIQUE KEY columns: ({}).", |
| 5089 | command.column_name, fmt::join(uk_column_names, ", ")); |
| 5090 | |
| 5091 | /// These commands rebuild whole parts (the full read+rewrite mutation path) and |
| 5092 | /// drop the delete_bitmap_*.rbm sidecars, silently resurrecting deleted rows once |
| 5093 | /// DELETE lands. MATERIALIZE INDEX/STATISTICS/PROJECTION reach the same path via |
| 5094 | /// MutateAllPartColumnsTask for compact or non-full parts (which only hardlinks |
| 5095 | /// checksummed entries, not the sidecars). Reject the whole destructive-rewrite family. |
| 5096 | if (command.type == MutationCommand::REWRITE_PARTS |
| 5097 | || command.type == MutationCommand::APPLY_DELETED_MASK |
| 5098 | || command.type == MutationCommand::APPLY_PATCHES |
| 5099 | || command.type == MutationCommand::MATERIALIZE_INDEX |
| 5100 | || command.type == MutationCommand::MATERIALIZE_STATISTICS |
| 5101 | || command.type == MutationCommand::MATERIALIZE_PROJECTION) |
| 5102 | throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, |
| 5103 | "ALTER TABLE ... {} is not supported on tables with UNIQUE KEY", |
nothing calls this directly
no test coverage detected