| 1137 | |
| 1138 | |
| 1139 | BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create) |
| 1140 | { |
| 1141 | /// Temporary tables are created out of databases. |
| 1142 | if (create.temporary && !create.database.empty()) |
| 1143 | throw Exception("Temporary tables cannot be inside a database. You should not specify a database for a temporary table.", |
| 1144 | ErrorCodes::BAD_DATABASE_FOR_TEMPORARY_TABLE); |
| 1145 | |
| 1146 | /// Need to judge create.columns_list to avoid possible core caused by: |
| 1147 | /// CREATE TABLE u10104_t2 Engine=CnchMergeTree UNIQUE KEY(a) AS SELECT * FROM u10104_t1; |
| 1148 | if (create.storage && create.storage->unique_key && create.columns_list && create.columns_list->projections) |
| 1149 | throw Exception("`Projection` cannot be used together with `UNIQUE KEY`", ErrorCodes::BAD_ARGUMENTS); |
| 1150 | |
| 1151 | String current_database = getContext()->getCurrentDatabase(); |
| 1152 | auto database_name = create.database.empty() ? current_database : create.database; |
| 1153 | |
| 1154 | // If this is a stub ATTACH query, read the query definition from the database |
| 1155 | if (create.attach && !create.storage && !create.columns_list) |
| 1156 | { |
| 1157 | auto database = DatabaseCatalog::instance().getDatabase(database_name, getContext()); |
| 1158 | |
| 1159 | if (database->getEngineName() == "Replicated") |
| 1160 | { |
| 1161 | auto guard = DatabaseCatalog::instance().getDDLGuard(database_name, create.table); |
| 1162 | |
| 1163 | if (auto* ptr = typeid_cast<DatabaseReplicated *>(database.get()); |
| 1164 | ptr && !getContext()->getClientInfo().is_replicated_database_internal) |
| 1165 | { |
| 1166 | create.database = database_name; |
| 1167 | guard->releaseTableLock(); |
| 1168 | return ptr->tryEnqueueReplicatedDDL(query_ptr, getContext()); |
| 1169 | } |
| 1170 | } |
| 1171 | |
| 1172 | bool if_not_exists = create.if_not_exists; |
| 1173 | |
| 1174 | // Table SQL definition is available even if the table is detached (even permanently) |
| 1175 | auto query = database->getCreateTableQuery(create.table, getContext()); |
| 1176 | auto create_query = query->as<ASTCreateQuery &>(); |
| 1177 | |
| 1178 | if (!create.is_dictionary && create_query.is_dictionary) |
| 1179 | throw Exception(ErrorCodes::INCORRECT_QUERY, |
| 1180 | "Cannot ATTACH TABLE {}.{}, it is a Dictionary", |
| 1181 | backQuoteIfNeed(database_name), backQuoteIfNeed(create.table)); |
| 1182 | |
| 1183 | if (create.is_dictionary && !create_query.is_dictionary) |
| 1184 | throw Exception(ErrorCodes::INCORRECT_QUERY, |
| 1185 | "Cannot ATTACH DICTIONARY {}.{}, it is a Table", |
| 1186 | backQuoteIfNeed(database_name), backQuoteIfNeed(create.table)); |
| 1187 | |
| 1188 | create = create_query; // Copy the saved create query, but use ATTACH instead of CREATE |
| 1189 | |
| 1190 | create.attach = true; |
| 1191 | create.attach_short_syntax = true; |
| 1192 | create.if_not_exists = if_not_exists; |
| 1193 | } |
| 1194 | |
| 1195 | /// TODO throw exception if !create.attach_short_syntax && !create.attach_from_path && !internal |
| 1196 |
no test coverage detected