| 21 | |
| 22 | |
| 23 | BlockIO InterpreterOptimizeQuery::execute() |
| 24 | { |
| 25 | const auto & ast = query_ptr->as<ASTOptimizeQuery &>(); |
| 26 | |
| 27 | if (!ast.cluster.empty()) |
| 28 | return executeDDLQueryOnCluster(query_ptr, getContext(), getRequiredAccess()); |
| 29 | |
| 30 | getContext()->checkAccess(getRequiredAccess()); |
| 31 | |
| 32 | auto table_id = getContext()->resolveStorageID(ast, Context::ResolveOrdinary); |
| 33 | StoragePtr table = DatabaseCatalog::instance().getTable(table_id, getContext()); |
| 34 | auto metadata_snapshot = table->getInMemoryMetadataPtr(); |
| 35 | auto storage_snapshot = table->getStorageSnapshot(metadata_snapshot, getContext()); |
| 36 | |
| 37 | // Empty list of names means we deduplicate by all columns, but user can explicitly state which columns to use. |
| 38 | Names column_names; |
| 39 | if (ast.deduplicate_by_columns) |
| 40 | { |
| 41 | // User requested custom set of columns for deduplication, possibly with Column Transformer expression. |
| 42 | { |
| 43 | // Expand asterisk, column transformers, etc into list of column names. |
| 44 | const auto cols |
| 45 | = processColumnTransformers(getContext()->getCurrentDatabase(), table, metadata_snapshot, ast.deduplicate_by_columns); |
| 46 | for (const auto & col : cols->children) |
| 47 | column_names.emplace_back(col->getColumnName()); |
| 48 | } |
| 49 | |
| 50 | storage_snapshot->check(column_names); |
| 51 | Names required_columns; |
| 52 | { |
| 53 | required_columns = metadata_snapshot->getColumnsRequiredForSortingKey(); |
| 54 | const auto partitioning_cols = metadata_snapshot->getColumnsRequiredForPartitionKey(); |
| 55 | required_columns.reserve(required_columns.size() + partitioning_cols.size()); |
| 56 | required_columns.insert(required_columns.end(), partitioning_cols.begin(), partitioning_cols.end()); |
| 57 | } |
| 58 | for (const auto & required_col : required_columns) |
| 59 | { |
| 60 | // Deduplication is performed only for adjacent rows in a block, |
| 61 | // and all rows in block are in the sorting key order within a single partition, |
| 62 | // hence deduplication always implicitly takes sorting keys and partition keys in account. |
| 63 | // So we just explicitly state that limitation in order to avoid confusion. |
| 64 | if (std::find(column_names.begin(), column_names.end(), required_col) == column_names.end()) |
| 65 | throw Exception(ErrorCodes::THERE_IS_NO_COLUMN, |
| 66 | "DEDUPLICATE BY expression must include all columns used in table's" |
| 67 | " ORDER BY, PRIMARY KEY, or PARTITION BY but '{}' is missing." |
| 68 | " Expanded DEDUPLICATE BY columns expression: ['{}']", |
| 69 | required_col, fmt::join(column_names, "', '")); |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | table->optimize(query_ptr, metadata_snapshot, ast.partition, ast.final, ast.deduplicate, column_names, getContext()); |
| 74 | |
| 75 | return {}; |
| 76 | } |
| 77 | |
| 78 | |
| 79 | AccessRightsElements InterpreterOptimizeQuery::getRequiredAccess() const |
nothing calls this directly
no test coverage detected