1#include <memory>
2
3#include <Poco/File.h>
4
5#include <Common/StringUtils/StringUtils.h>
6#include <Common/escapeForFileName.h>
7#include <Common/typeid_cast.h>
8
9#include <IO/WriteBufferFromFile.h>
10#include <IO/WriteHelpers.h>
11
12#include <Parsers/ASTColumnDeclaration.h>
13#include <Parsers/ASTCreateQuery.h>
14#include <Parsers/ASTIdentifier.h>
15#include <Parsers/ASTIndexDeclaration.h>
16#include <Parsers/ASTLiteral.h>
17#include <Parsers/ASTNameTypePair.h>
18#include <Parsers/ASTInsertQuery.h>
19#include <Parsers/ParserCreateQuery.h>
20#include <Parsers/formatAST.h>
21#include <Parsers/parseQuery.h>
22
23#include <Storages/StorageFactory.h>
24
25#include <Interpreters/Context.h>
26#include <Interpreters/DDLWorker.h>
27#include <Interpreters/ExpressionAnalyzer.h>
28#include <Interpreters/SyntaxAnalyzer.h>
29#include <Interpreters/InterpreterCreateQuery.h>
30#include <Interpreters/InterpreterSelectWithUnionQuery.h>
31#include <Interpreters/InterpreterInsertQuery.h>
32#include <Interpreters/ExpressionActions.h>
33#include <Interpreters/AddDefaultDatabaseVisitor.h>
34
35#include <DataTypes/DataTypeFactory.h>
36#include <DataTypes/NestedUtils.h>
37#include <DataTypes/DataTypesNumber.h>
38#include <DataTypes/DataTypeLowCardinality.h>
39#include <DataTypes/DataTypeNullable.h>
40
41#include <Databases/DatabaseFactory.h>
42#include <Databases/IDatabase.h>
43
44#include <Compression/CompressionFactory.h>
45
46#include <Interpreters/InterpreterDropQuery.h>
47#include <Interpreters/addTypeConversionToAST.h>
48
49#include <TableFunctions/TableFunctionFactory.h>
50
51
52namespace DB
53{
54
55namespace ErrorCodes
56{
57 extern const int TABLE_ALREADY_EXISTS;
58 extern const int EMPTY_LIST_OF_COLUMNS_PASSED;
59 extern const int INCORRECT_QUERY;
60 extern const int ENGINE_REQUIRED;
61 extern const int UNKNOWN_DATABASE_ENGINE;
62 extern const int DUPLICATE_COLUMN;
63 extern const int READONLY;
64 extern const int ILLEGAL_COLUMN;
65 extern const int DATABASE_ALREADY_EXISTS;
66 extern const int QUERY_IS_PROHIBITED;
67 extern const int THERE_IS_NO_DEFAULT_VALUE;
68 extern const int BAD_DATABASE_FOR_TEMPORARY_TABLE;
69 extern const int SUSPICIOUS_TYPE_FOR_LOW_CARDINALITY;
70 extern const int DICTIONARY_ALREADY_EXISTS;
71}
72
73
74InterpreterCreateQuery::InterpreterCreateQuery(const ASTPtr & query_ptr_, Context & context_)
75 : query_ptr(query_ptr_), context(context_)
76{
77}
78
79
80BlockIO InterpreterCreateQuery::createDatabase(ASTCreateQuery & create)
81{
82 if (!create.cluster.empty())
83 return executeDDLQueryOnCluster(query_ptr, context, {create.database});
84
85 String database_name = create.database;
86
87 auto guard = context.getDDLGuard(database_name, "");
88
89 /// Database can be created before or it can be created concurrently in another thread, while we were waiting in DDLGuard
90 if (context.isDatabaseExist(database_name))
91 {
92 if (create.if_not_exists)
93 return {};
94 else
95 throw Exception("Database " + database_name + " already exists.", ErrorCodes::DATABASE_ALREADY_EXISTS);
96 }
97
98 if (!create.storage)
99 {
100 auto engine = std::make_shared<ASTFunction>();
101 auto storage = std::make_shared<ASTStorage>();
102 engine->name = "Ordinary";
103 storage->set(storage->engine, engine);
104 create.set(create.storage, storage);
105 }
106 else if ((create.columns_list && create.columns_list->indices && !create.columns_list->indices->children.empty()))
107 {
108 /// Currently, there are no database engines, that support any arguments.
109 std::stringstream ostr;
110 formatAST(*create.storage, ostr, false, false);
111 throw Exception("Unknown database engine: " + ostr.str(), ErrorCodes::UNKNOWN_DATABASE_ENGINE);
112 }
113
114 String database_name_escaped = escapeForFileName(database_name);
115
116 /// Create directories for tables metadata.
117 String path = context.getPath();
118 String metadata_path = path + "metadata/" + database_name_escaped + "/";
119 DatabasePtr database = DatabaseFactory::get(database_name, metadata_path, create.storage, context);
120
121 /// Will write file with database metadata, if needed.
122 String metadata_file_tmp_path = path + "metadata/" + database_name_escaped + ".sql.tmp";
123 String metadata_file_path = path + "metadata/" + database_name_escaped + ".sql";
124
125 bool need_write_metadata = !create.attach;
126
127 if (need_write_metadata)
128 {
129 create.attach = true;
130 create.if_not_exists = false;
131
132 std::ostringstream statement_stream;
133 formatAST(create, statement_stream, false);
134 statement_stream << '\n';
135 String statement = statement_stream.str();
136
137 /// Exclusive flag guarantees, that database is not created right now in another thread.
138 WriteBufferFromFile out(metadata_file_tmp_path, statement.size(), O_WRONLY | O_CREAT | O_EXCL);
139 writeString(statement, out);
140
141 out.next();
142 if (context.getSettingsRef().fsync_metadata)
143 out.sync();
144 out.close();
145 }
146
147 bool added = false;
148 bool renamed = false;
149 try
150 {
151 context.addDatabase(database_name, database);
152 added = true;
153
154 if (need_write_metadata)
155 {
156 Poco::File(metadata_file_tmp_path).renameTo(metadata_file_path);
157 renamed = true;
158 }
159
160 database->loadStoredObjects(context, has_force_restore_data_flag);
161 }
162 catch (...)
163 {
164 if (renamed)
165 Poco::File(metadata_file_tmp_path).remove();
166 if (added)
167 context.detachDatabase(database_name);
168
169 throw;
170 }
171
172 return {};
173}
174
175
176ASTPtr InterpreterCreateQuery::formatColumns(const NamesAndTypesList & columns)
177{
178 auto columns_list = std::make_shared<ASTExpressionList>();
179
180 for (const auto & column : columns)
181 {
182 const auto column_declaration = std::make_shared<ASTColumnDeclaration>();
183 column_declaration->name = column.name;
184
185 ParserIdentifierWithOptionalParameters storage_p;
186 String type_name = column.type->getName();
187 auto pos = type_name.data();
188 const auto end = pos + type_name.size();
189 column_declaration->type = parseQuery(storage_p, pos, end, "data type", 0);
190 columns_list->children.emplace_back(column_declaration);
191 }
192
193 return columns_list;
194}
195
196ASTPtr InterpreterCreateQuery::formatColumns(const ColumnsDescription & columns)
197{
198 auto columns_list = std::make_shared<ASTExpressionList>();
199
200 for (const auto & column : columns)
201 {
202 /// Do not include virtual columns
203 if (column.is_virtual)
204 continue;
205
206 const auto column_declaration = std::make_shared<ASTColumnDeclaration>();
207 ASTPtr column_declaration_ptr{column_declaration};
208
209 column_declaration->name = column.name;
210
211 ParserIdentifierWithOptionalParameters storage_p;
212 String type_name = column.type->getName();
213 auto type_name_pos = type_name.data();
214 const auto type_name_end = type_name_pos + type_name.size();
215 column_declaration->type = parseQuery(storage_p, type_name_pos, type_name_end, "data type", 0);
216
217 if (column.default_desc.expression)
218 {
219 column_declaration->default_specifier = toString(column.default_desc.kind);
220 column_declaration->default_expression = column.default_desc.expression->clone();
221 }
222
223 if (!column.comment.empty())
224 {
225 column_declaration->comment = std::make_shared<ASTLiteral>(Field(column.comment));
226 }
227
228 if (column.codec)
229 {
230 String codec_desc = column.codec->getCodecDesc();
231 codec_desc = "CODEC(" + codec_desc + ")";
232 auto codec_desc_pos = codec_desc.data();
233 const auto codec_desc_end = codec_desc_pos + codec_desc.size();
234 ParserIdentifierWithParameters codec_p;
235 column_declaration->codec = parseQuery(codec_p, codec_desc_pos, codec_desc_end, "column codec", 0);
236 }
237
238 if (column.ttl)
239 column_declaration->ttl = column.ttl;
240
241 columns_list->children.push_back(column_declaration_ptr);
242 }
243
244 return columns_list;
245}
246
247ASTPtr InterpreterCreateQuery::formatIndices(const IndicesDescription & indices)
248{
249 auto res = std::make_shared<ASTExpressionList>();
250
251 for (const auto & index : indices.indices)
252 res->children.push_back(index->clone());
253
254 return res;
255}
256
257ASTPtr InterpreterCreateQuery::formatConstraints(const ConstraintsDescription & constraints)
258{
259 auto res = std::make_shared<ASTExpressionList>();
260
261 for (const auto & constraint : constraints.constraints)
262 res->children.push_back(constraint->clone());
263
264 return res;
265}
266
267ColumnsDescription InterpreterCreateQuery::getColumnsDescription(const ASTExpressionList & columns_ast, const Context & context)
268{
269 /// First, deduce implicit types.
270
271 /** all default_expressions as a single expression list,
272 * mixed with conversion-columns for each explicitly specified type */
273 ASTPtr default_expr_list = std::make_shared<ASTExpressionList>();
274 NamesAndTypesList column_names_and_types;
275
276 for (const auto & ast : columns_ast.children)
277 {
278 const auto & col_decl = ast->as<ASTColumnDeclaration &>();
279
280 DataTypePtr column_type = nullptr;
281 if (col_decl.type)
282 {
283 column_type = DataTypeFactory::instance().get(col_decl.type);
284 column_names_and_types.emplace_back(col_decl.name, column_type);
285 }
286 else
287 {
288 /// we're creating dummy DataTypeUInt8 in order to prevent the NullPointerException in ExpressionActions
289 column_names_and_types.emplace_back(col_decl.name, std::make_shared<DataTypeUInt8>());
290 }
291
292 /// add column to postprocessing if there is a default_expression specified
293 if (col_decl.default_expression)
294 {
295 /** For columns with explicitly-specified type create two expressions:
296 * 1. default_expression aliased as column name with _tmp suffix
297 * 2. conversion of expression (1) to explicitly-specified type alias as column name
298 */
299 if (col_decl.type)
300 {
301 const auto & final_column_name = col_decl.name;
302 const auto tmp_column_name = final_column_name + "_tmp";
303 const auto data_type_ptr = column_names_and_types.back().type.get();
304
305
306 default_expr_list->children.emplace_back(
307 setAlias(addTypeConversionToAST(std::make_shared<ASTIdentifier>(tmp_column_name), data_type_ptr->getName()),
308 final_column_name));
309
310 default_expr_list->children.emplace_back(
311 setAlias(
312 col_decl.default_expression->clone(),
313 tmp_column_name));
314 }
315 else
316 default_expr_list->children.emplace_back(setAlias(col_decl.default_expression->clone(), col_decl.name));
317 }
318 }
319
320 Block defaults_sample_block;
321 /// set missing types and wrap default_expression's in a conversion-function if necessary
322 if (!default_expr_list->children.empty())
323 {
324 auto syntax_analyzer_result = SyntaxAnalyzer(context).analyze(default_expr_list, column_names_and_types);
325 const auto actions = ExpressionAnalyzer(default_expr_list, syntax_analyzer_result, context).getActions(true);
326 for (auto action : actions->getActions())
327 if (action.type == ExpressionAction::Type::JOIN || action.type == ExpressionAction::Type::ARRAY_JOIN)
328 throw Exception("Cannot CREATE table. Unsupported default value that requires ARRAY JOIN or JOIN action", ErrorCodes::THERE_IS_NO_DEFAULT_VALUE);
329
330 defaults_sample_block = actions->getSampleBlock();
331 }
332
333 ColumnsDescription res;
334 auto name_type_it = column_names_and_types.begin();
335 for (auto ast_it = columns_ast.children.begin(); ast_it != columns_ast.children.end(); ++ast_it, ++name_type_it)
336 {
337 ColumnDescription column;
338
339 auto & col_decl = (*ast_it)->as<ASTColumnDeclaration &>();
340
341 column.name = col_decl.name;
342
343 if (col_decl.default_expression)
344 {
345 ASTPtr default_expr = col_decl.default_expression->clone();
346 if (col_decl.type)
347 {
348 const auto & deduced_type = defaults_sample_block.getByName(column.name + "_tmp").type;
349 column.type = name_type_it->type;
350
351 if (!column.type->equals(*deduced_type))
352 default_expr = addTypeConversionToAST(std::move(default_expr), column.type->getName());
353 }
354 else
355 column.type = defaults_sample_block.getByName(column.name).type;
356
357 column.default_desc.kind = columnDefaultKindFromString(col_decl.default_specifier);
358 column.default_desc.expression = default_expr;
359 }
360 else if (col_decl.type)
361 column.type = name_type_it->type;
362 else
363 throw Exception();
364
365 if (col_decl.comment)
366 column.comment = col_decl.comment->as<ASTLiteral &>().value.get<String>();
367
368 if (col_decl.codec)
369 column.codec = CompressionCodecFactory::instance().get(col_decl.codec, column.type);
370
371 if (col_decl.ttl)
372 column.ttl = col_decl.ttl;
373
374 res.add(std::move(column));
375 }
376
377 res.flattenNested();
378
379 if (res.getAllPhysical().empty())
380 throw Exception{"Cannot CREATE table without physical columns", ErrorCodes::EMPTY_LIST_OF_COLUMNS_PASSED};
381
382 return res;
383}
384
385
386ConstraintsDescription InterpreterCreateQuery::getConstraintsDescription(const ASTExpressionList * constraints)
387{
388 ConstraintsDescription res;
389 if (constraints)
390 for (const auto & constraint : constraints->children)
391 res.constraints.push_back(std::dynamic_pointer_cast<ASTConstraintDeclaration>(constraint->clone()));
392 return res;
393}
394
395
396InterpreterCreateQuery::TableProperties InterpreterCreateQuery::setProperties(ASTCreateQuery & create) const
397{
398 TableProperties properties;
399 TableStructureReadLockHolder as_storage_lock;
400
401 if (create.columns_list)
402 {
403 if (create.columns_list->columns)
404 properties.columns = getColumnsDescription(*create.columns_list->columns, context);
405
406 if (create.columns_list->indices)
407 for (const auto & index : create.columns_list->indices->children)
408 properties.indices.indices.push_back(
409 std::dynamic_pointer_cast<ASTIndexDeclaration>(index->clone()));
410
411 properties.constraints = getConstraintsDescription(create.columns_list->constraints);
412 }
413 else if (!create.as_table.empty())
414 {
415 String as_database_name = create.as_database.empty() ? context.getCurrentDatabase() : create.as_database;
416 StoragePtr as_storage = context.getTable(as_database_name, create.as_table);
417
418 /// as_storage->getColumns() and setEngine(...) must be called under structure lock of other_table for CREATE ... AS other_table.
419 as_storage_lock = as_storage->lockStructureForShare(false, context.getCurrentQueryId());
420 properties.columns = as_storage->getColumns();
421
422 /// Secondary indices make sense only for MergeTree family of storage engines.
423 /// We should not copy them for other storages.
424 if (create.storage && endsWith(create.storage->engine->name, "MergeTree"))
425 properties.indices = as_storage->getIndices();
426
427 properties.constraints = as_storage->getConstraints();
428 }
429 else if (create.select)
430 {
431 Block as_select_sample = InterpreterSelectWithUnionQuery::getSampleBlock(create.select->clone(), context);
432 properties.columns = ColumnsDescription(as_select_sample.getNamesAndTypesList());
433 }
434 else if (create.as_table_function)
435 return {};
436 else
437 throw Exception("Incorrect CREATE query: required list of column descriptions or AS section or SELECT.", ErrorCodes::INCORRECT_QUERY);
438
439
440 /// Even if query has list of columns, canonicalize it (unfold Nested columns).
441 if (!create.columns_list)
442 create.set(create.columns_list, std::make_shared<ASTColumns>());
443
444 ASTPtr new_columns = formatColumns(properties.columns);
445 ASTPtr new_indices = formatIndices(properties.indices);
446 ASTPtr new_constraints = formatConstraints(properties.constraints);
447
448 create.columns_list->setOrReplace(create.columns_list->columns, new_columns);
449 create.columns_list->setOrReplace(create.columns_list->indices, new_indices);
450 create.columns_list->setOrReplace(create.columns_list->constraints, new_constraints);
451
452 validateTableStructure(create, properties);
453
454 /// Set the table engine if it was not specified explicitly.
455 setEngine(create);
456 return properties;
457}
458
459void InterpreterCreateQuery::validateTableStructure(const ASTCreateQuery & create,
460 const InterpreterCreateQuery::TableProperties & properties) const
461{
462 /// Check for duplicates
463 std::set<String> all_columns;
464 for (const auto & column : properties.columns)
465 {
466 if (!all_columns.emplace(column.name).second)
467 throw Exception("Column " + backQuoteIfNeed(column.name) + " already exists", ErrorCodes::DUPLICATE_COLUMN);
468 }
469
470 /// Check low cardinality types in creating table if it was not allowed in setting
471 if (!create.attach && !context.getSettingsRef().allow_suspicious_low_cardinality_types && !create.is_materialized_view)
472 {
473 for (const auto & name_and_type_pair : properties.columns.getAllPhysical())
474 {
475 if (const auto * current_type_ptr = typeid_cast<const DataTypeLowCardinality *>(name_and_type_pair.type.get()))
476 {
477 if (!isStringOrFixedString(*removeNullable(current_type_ptr->getDictionaryType())))
478 throw Exception("Creating columns of type " + current_type_ptr->getName() + " is prohibited by default "
479 "due to expected negative impact on performance. "
480 "It can be enabled with the \"allow_suspicious_low_cardinality_types\" setting.",
481 ErrorCodes::SUSPICIOUS_TYPE_FOR_LOW_CARDINALITY);
482 }
483 }
484 }
485}
486
487void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const
488{
489 if (create.storage)
490 {
491 if (create.temporary && create.storage->engine->name != "Memory")
492 throw Exception(
493 "Temporary tables can only be created with ENGINE = Memory, not " + create.storage->engine->name,
494 ErrorCodes::INCORRECT_QUERY);
495
496 return;
497 }
498
499 if (create.temporary && !create.is_live_view)
500 {
501 auto engine_ast = std::make_shared<ASTFunction>();
502 engine_ast->name = "Memory";
503 auto storage_ast = std::make_shared<ASTStorage>();
504 storage_ast->set(storage_ast->engine, engine_ast);
505 create.set(create.storage, storage_ast);
506 }
507 else if (!create.as_table.empty())
508 {
509 /// NOTE Getting the structure from the table specified in the AS is done not atomically with the creation of the table.
510
511 String as_database_name = create.as_database.empty() ? context.getCurrentDatabase() : create.as_database;
512 String as_table_name = create.as_table;
513
514 ASTPtr as_create_ptr = context.getDatabase(as_database_name)->getCreateTableQuery(context, as_table_name);
515 const auto & as_create = as_create_ptr->as<ASTCreateQuery &>();
516
517 if (as_create.is_view)
518 throw Exception(
519 "Cannot CREATE a table AS " + as_database_name + "." + as_table_name + ", it is a View",
520 ErrorCodes::INCORRECT_QUERY);
521
522 if (as_create.is_live_view)
523 throw Exception(
524 "Cannot CREATE a table AS " + as_database_name + "." + as_table_name + ", it is a Live View",
525 ErrorCodes::INCORRECT_QUERY);
526
527 create.set(create.storage, as_create.storage->ptr());
528 }
529}
530
531
532BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
533{
534 if (!create.cluster.empty())
535 {
536 NameSet databases{create.database};
537 if (!create.to_table.empty())
538 databases.emplace(create.to_database);
539
540 return executeDDLQueryOnCluster(query_ptr, context, std::move(databases));
541 }
542
543 /// Temporary tables are created out of databases.
544 if (create.temporary && !create.database.empty() && !create.is_live_view)
545 throw Exception("Temporary tables cannot be inside a database. You should not specify a database for a temporary table.",
546 ErrorCodes::BAD_DATABASE_FOR_TEMPORARY_TABLE);
547
548 // If this is a stub ATTACH query, read the query definition from the database
549 if (create.attach && !create.storage && !create.columns_list)
550 {
551 // Table SQL definition is available even if the table is detached
552 auto query = context.getDatabase(create.database)->getCreateTableQuery(context, create.table);
553 create = query->as<ASTCreateQuery &>(); // Copy the saved create query, but use ATTACH instead of CREATE
554 create.attach = true;
555 }
556
557 String current_database = context.getCurrentDatabase();
558 if (!create.temporary && create.database.empty())
559 create.database = current_database;
560 if (!create.to_table.empty() && create.to_database.empty())
561 create.to_database = current_database;
562
563 if (create.select && (create.is_view || create.is_materialized_view || create.is_live_view))
564 {
565 AddDefaultDatabaseVisitor visitor(current_database);
566 visitor.visit(*create.select);
567 }
568
569 /// Set and retrieve list of columns, indices and constraints. Set table engine if needed. Rewrite query in canonical way.
570 TableProperties properties = setProperties(create);
571
572 /// Actually creates table
573 bool created = doCreateTable(create, properties);
574
575 if (!created) /// Table already exists
576 return {};
577
578 return fillTableIfNeeded(create);
579}
580
581bool InterpreterCreateQuery::doCreateTable(const ASTCreateQuery & create,
582 const InterpreterCreateQuery::TableProperties & properties)
583{
584 std::unique_ptr<DDLGuard> guard;
585
586 DatabasePtr database;
587
588 const String & table_name = create.table;
589 bool need_add_to_database = !create.temporary || create.is_live_view;
590 if (need_add_to_database)
591 {
592 database = context.getDatabase(create.database);
593
594 /** If the request specifies IF NOT EXISTS, we allow concurrent CREATE queries (which do nothing).
595 * If table doesnt exist, one thread is creating table, while others wait in DDLGuard.
596 */
597 guard = context.getDDLGuard(create.database, table_name);
598
599 /// Table can be created before or it can be created concurrently in another thread, while we were waiting in DDLGuard.
600 if (database->isTableExist(context, table_name))
601 {
602 /// TODO Check structure of table
603 if (create.if_not_exists)
604 return false;
605 else if (create.replace_view)
606 {
607 /// when executing CREATE OR REPLACE VIEW, drop current existing view
608 auto drop_ast = std::make_shared<ASTDropQuery>();
609 drop_ast->database = create.database;
610 drop_ast->table = table_name;
611 drop_ast->no_ddl_lock = true;
612
613 InterpreterDropQuery interpreter(drop_ast, context);
614 interpreter.execute();
615 }
616 else
617 throw Exception("Table " + create.database + "." + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
618 }
619 }
620 else if (context.tryGetExternalTable(table_name) && create.if_not_exists)
621 return false;
622
623 StoragePtr res;
624 if (create.as_table_function)
625 {
626 const auto & table_function = create.as_table_function->as<ASTFunction &>();
627 const auto & factory = TableFunctionFactory::instance();
628 res = factory.get(table_function.name, context)->execute(create.as_table_function, context, create.table);
629 }
630 else
631 {
632 res = StorageFactory::instance().get(create,
633 database ? database->getTableDataPath(create) : "",
634 table_name,
635 create.database,
636 context,
637 context.getGlobalContext(),
638 properties.columns,
639 properties.constraints,
640 create.attach,
641 false);
642 }
643
644 if (need_add_to_database)
645 database->createTable(context, table_name, res, query_ptr);
646 else
647 context.getSessionContext().addExternalTable(table_name, res, query_ptr);
648
649 /// We must call "startup" and "shutdown" while holding DDLGuard.
650 /// Because otherwise method "shutdown" (from InterpreterDropQuery) can be called before startup
651 /// (in case when table was created and instantly dropped before started up)
652 ///
653 /// Method "startup" may create background tasks and method "shutdown" will wait for them.
654 /// But if "shutdown" is called before "startup", it will exit early, because there are no background tasks to wait.
655 /// Then background task is created by "startup" method. And when destructor of a table object is called, background task is still active,
656 /// and the task will use references to freed data.
657
658 res->startup();
659 return true;
660}
661
662BlockIO InterpreterCreateQuery::fillTableIfNeeded(const ASTCreateQuery & create)
663{
664 /// If the query is a CREATE SELECT, insert the data into the table.
665 if (create.select && !create.attach
666 && !create.is_view && !create.is_live_view && (!create.is_materialized_view || create.is_populate))
667 {
668 auto insert = std::make_shared<ASTInsertQuery>();
669
670 if (!create.temporary)
671 insert->database = create.database;
672
673 insert->table = create.table;
674 insert->select = create.select->clone();
675
676 if (create.temporary && !context.getSessionContext().hasQueryContext())
677 context.getSessionContext().makeQueryContext();
678
679 return InterpreterInsertQuery(insert,
680 create.temporary ? context.getSessionContext() : context,
681 context.getSettingsRef().insert_allow_materialized_columns).execute();
682 }
683
684 return {};
685}
686
687BlockIO InterpreterCreateQuery::createDictionary(ASTCreateQuery & create)
688{
689 if (!create.cluster.empty())
690 return executeDDLQueryOnCluster(query_ptr, context, {create.database});
691
692 String dictionary_name = create.table;
693
694 if (create.database.empty())
695 create.database = context.getCurrentDatabase();
696 const String & database_name = create.database;
697
698 auto guard = context.getDDLGuard(database_name, dictionary_name);
699 DatabasePtr database = context.getDatabase(database_name);
700
701 if (database->isDictionaryExist(context, dictionary_name))
702 {
703 /// TODO Check structure of dictionary
704 if (create.if_not_exists)
705 return {};
706 else
707 throw Exception(
708 "Dictionary " + database_name + "." + dictionary_name + " already exists.", ErrorCodes::DICTIONARY_ALREADY_EXISTS);
709 }
710
711 if (create.attach)
712 {
713 auto query = context.getDatabase(database_name)->getCreateDictionaryQuery(context, dictionary_name);
714 create = query->as<ASTCreateQuery &>();
715 create.attach = true;
716 }
717
718 if (create.attach)
719 database->attachDictionary(dictionary_name, context);
720 else
721 database->createDictionary(context, dictionary_name, query_ptr);
722
723 return {};
724}
725
726BlockIO InterpreterCreateQuery::execute()
727{
728 auto & create = query_ptr->as<ASTCreateQuery &>();
729 checkAccess(create);
730 ASTQueryWithOutput::resetOutputASTIfExist(create);
731
732 /// CREATE|ATTACH DATABASE
733 if (!create.database.empty() && create.table.empty())
734 return createDatabase(create);
735 else if (!create.is_dictionary)
736 return createTable(create);
737 else
738 return createDictionary(create);
739}
740
741
742void InterpreterCreateQuery::checkAccess(const ASTCreateQuery & create)
743{
744 /// Internal queries (initiated by the server itself) always have access to everything.
745 if (internal)
746 return;
747
748 const Settings & settings = context.getSettingsRef();
749 auto readonly = settings.readonly;
750 auto allow_ddl = settings.allow_ddl;
751
752 if (!readonly && allow_ddl)
753 return;
754
755 /// CREATE|ATTACH DATABASE
756 if (!create.database.empty() && create.table.empty())
757 {
758 if (readonly)
759 throw Exception("Cannot create database in readonly mode", ErrorCodes::READONLY);
760
761 throw Exception("Cannot create database. DDL queries are prohibited for the user", ErrorCodes::QUERY_IS_PROHIBITED);
762 }
763 String object = "table";
764
765 if (create.is_dictionary)
766 {
767 if (readonly)
768 throw Exception("Cannot create dictionary in readonly mode", ErrorCodes::READONLY);
769 object = "dictionary";
770 }
771
772 if (create.temporary && readonly >= 2)
773 return;
774
775 if (readonly)
776 throw Exception("Cannot create table or dictionary in readonly mode", ErrorCodes::READONLY);
777
778 throw Exception("Cannot create " + object + ". DDL queries are prohibited for the user", ErrorCodes::QUERY_IS_PROHIBITED);
779}
780
781}
782