| 1548 | } |
| 1549 | |
| 1550 | BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create) |
| 1551 | { |
| 1552 | auto component_guard = Coordination::setCurrentComponent("InterpreterCreateQuery::createTable"); |
| 1553 | /// Temporary tables are created out of databases. |
| 1554 | if (create.isTemporary() && create.attach) |
| 1555 | throw Exception(ErrorCodes::SYNTAX_ERROR, "ATTACH of TEMPORARY tables are not supported"); |
| 1556 | |
| 1557 | if (create.isTemporary() && create.database) |
| 1558 | throw Exception(ErrorCodes::BAD_DATABASE_FOR_TEMPORARY_TABLE, |
| 1559 | "Temporary objects (tables/views) cannot be inside a database. " |
| 1560 | "You should not specify a database for a temporary objects."); |
| 1561 | |
| 1562 | if (create.isTemporary() && !create.cluster.empty()) |
| 1563 | throw Exception(ErrorCodes::INCORRECT_QUERY, |
| 1564 | "Temporary objects (tables/views) cannot be created ON CLUSTER." |
| 1565 | "You should not specify a cluster for a temporary objects."); |
| 1566 | |
| 1567 | String current_database = getContext()->getCurrentDatabase(); |
| 1568 | auto database_name = create.database ? create.getDatabase() : current_database; |
| 1569 | |
| 1570 | bool is_secondary_query = getContext()->getZooKeeperMetadataTransaction() && !getContext()->getZooKeeperMetadataTransaction()->isInitialQuery(); |
| 1571 | auto mode = getLoadingStrictnessLevel(create.attach, /*force_attach*/ false, /*has_force_restore_data_flag*/ false, is_secondary_query || is_restore_from_backup); |
| 1572 | |
| 1573 | if (!create.sql_security && create.supportSQLSecurity() && (create.refresh_strategy || !getContext()->getServerSettings()[ServerSetting::ignore_empty_sql_security_in_create_view_query])) |
| 1574 | create.set(create.sql_security, make_intrusive<ASTSQLSecurity>()); |
| 1575 | |
| 1576 | if (create.sql_security) |
| 1577 | processSQLSecurityOption(getContext(), create.sql_security->as<ASTSQLSecurity &>(), create.is_materialized_view, mode); |
| 1578 | |
| 1579 | DDLGuardPtr ddl_guard; |
| 1580 | |
| 1581 | // If this is a stub ATTACH query, read the query definition from the database |
| 1582 | if (create.attach && (!create.storage || !create.storage->engine) && !create.columns_list) |
| 1583 | { |
| 1584 | /// First, reject any user-supplied storage clauses or top-level fields that the |
| 1585 | /// short-ATTACH path below would silently drop by overwriting `create` with the |
| 1586 | /// stored table metadata. `InterpreterSetQuery::applySettingsFromQuery` (called from |
| 1587 | /// `executeQueryImpl` before this interpreter) has already hoisted session settings |
| 1588 | /// out of `create.storage->settings`, so anything still here is either engine-specific |
| 1589 | /// (`ORDER BY`, `PARTITION BY`, `PRIMARY KEY`, `SAMPLE BY`, `TTL`, `UNIQUE KEY`, MergeTree |
| 1590 | /// `SETTINGS`) or a top-level `ASTCreateQuery` field (`COMMENT`, `REFRESH`, `SQL SECURITY`, |
| 1591 | /// `TO target`, `EMPTY`, `CLONE`, `AS SELECT`, `UUID`, etc.). |
| 1592 | bool has_dropped_clauses = false; |
| 1593 | |
| 1594 | if (create.storage) |
| 1595 | { |
| 1596 | const auto & storage = *create.storage; |
| 1597 | has_dropped_clauses |
| 1598 | = storage.partition_by != nullptr |
| 1599 | || storage.primary_key != nullptr |
| 1600 | || storage.order_by != nullptr |
| 1601 | || storage.sample_by != nullptr |
| 1602 | || storage.ttl_table != nullptr |
| 1603 | || storage.unique_key != nullptr |
| 1604 | || storage.settings != nullptr; |
| 1605 | } |
| 1606 | |
| 1607 | has_dropped_clauses = has_dropped_clauses |
no test coverage detected