#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace DB { bool ParserNestedTable::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserToken open(TokenType::OpeningRoundBracket); ParserToken close(TokenType::ClosingRoundBracket); ParserIdentifier name_p; ParserNameTypePairList columns_p; ASTPtr name; ASTPtr columns; /// For now `name == 'Nested'`, probably alternative nested data structures will appear if (!name_p.parse(pos, name, expected)) return false; if (!open.ignore(pos)) return false; if (!columns_p.parse(pos, columns, expected)) return false; if (!close.ignore(pos)) return false; auto func = std::make_shared(); tryGetIdentifierNameInto(name, func->name); func->arguments = columns; func->children.push_back(columns); node = func; return true; } bool ParserIdentifierWithParameters::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserFunction().parse(pos, node, expected); } bool ParserNameTypePairList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserList(std::make_unique(), std::make_unique(TokenType::Comma), false) .parse(pos, node, expected); } bool ParserColumnDeclarationList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserList(std::make_unique(), std::make_unique(TokenType::Comma), false) .parse(pos, node, expected); } bool ParserNameList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserList(std::make_unique(), std::make_unique(TokenType::Comma), false) .parse(pos, node, expected); } bool ParserIndexDeclaration::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_type("TYPE"); ParserKeyword s_granularity("GRANULARITY"); ParserIdentifier name_p; ParserDataType data_type_p; ParserExpression expression_p; ParserUnsignedInteger granularity_p; ASTPtr name; ASTPtr expr; ASTPtr type; ASTPtr granularity; if (!name_p.parse(pos, name, expected)) return false; if (!expression_p.parse(pos, expr, expected)) return false; if (!s_type.ignore(pos, expected)) return false; if (!data_type_p.parse(pos, type, expected)) return false; if (!s_granularity.ignore(pos, expected)) return false; if (!granularity_p.parse(pos, granularity, expected)) return false; auto index = std::make_shared(); index->name = name->as().name; index->granularity = granularity->as().value.safeGet(); index->set(index->expr, expr); index->set(index->type, type); node = index; return true; } bool ParserConstraintDeclaration::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_check("CHECK"); ParserIdentifier name_p; ParserLogicalOrExpression expression_p; ASTPtr name; ASTPtr expr; if (!name_p.parse(pos, name, expected)) return false; if (!s_check.ignore(pos, expected)) return false; if (!expression_p.parse(pos, expr, expected)) return false; auto constraint = std::make_shared(); constraint->name = name->as().name; constraint->set(constraint->expr, expr); node = constraint; return true; } bool ParserTablePropertyDeclaration::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_index("INDEX"); ParserKeyword s_constraint("CONSTRAINT"); ParserIndexDeclaration index_p; ParserConstraintDeclaration constraint_p; ParserColumnDeclaration column_p{true, true}; ASTPtr new_node = nullptr; if (s_index.ignore(pos, expected)) { if (!index_p.parse(pos, new_node, expected)) return false; } else if (s_constraint.ignore(pos, expected)) { if (!constraint_p.parse(pos, new_node, expected)) return false; } else { if (!column_p.parse(pos, new_node, expected)) return false; } node = new_node; return true; } bool ParserIndexDeclarationList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserList(std::make_unique(), std::make_unique(TokenType::Comma), false) .parse(pos, node, expected); } bool ParserConstraintDeclarationList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserList(std::make_unique(), std::make_unique(TokenType::Comma), false) .parse(pos, node, expected); } bool ParserTablePropertiesDeclarationList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ASTPtr list; if (!ParserList( std::make_unique(), std::make_unique(TokenType::Comma), false) .parse(pos, list, expected)) return false; ASTPtr columns = std::make_shared(); ASTPtr indices = std::make_shared(); ASTPtr constraints = std::make_shared(); for (const auto & elem : list->children) { if (elem->as()) columns->children.push_back(elem); else if (elem->as()) indices->children.push_back(elem); else if (elem->as()) constraints->children.push_back(elem); else return false; } auto res = std::make_shared(); if (!columns->children.empty()) res->set(res->columns, columns); if (!indices->children.empty()) res->set(res->indices, indices); if (!constraints->children.empty()) res->set(res->constraints, constraints); node = res; return true; } bool ParserStorage::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_engine("ENGINE"); ParserToken s_eq(TokenType::Equals); ParserKeyword s_partition_by("PARTITION BY"); ParserKeyword s_primary_key("PRIMARY KEY"); ParserKeyword s_order_by("ORDER BY"); ParserKeyword s_sample_by("SAMPLE BY"); ParserKeyword s_ttl("TTL"); ParserKeyword s_settings("SETTINGS"); ParserIdentifierWithOptionalParameters ident_with_optional_params_p; ParserExpression expression_p; ParserSetQuery settings_p(/* parse_only_internals_ = */ true); ParserTTLExpressionList parser_ttl_list; ASTPtr engine; ASTPtr partition_by; ASTPtr primary_key; ASTPtr order_by; ASTPtr sample_by; ASTPtr ttl_table; ASTPtr settings; if (!s_engine.ignore(pos, expected)) return false; s_eq.ignore(pos, expected); if (!ident_with_optional_params_p.parse(pos, engine, expected)) return false; while (true) { if (!partition_by && s_partition_by.ignore(pos, expected)) { if (expression_p.parse(pos, partition_by, expected)) continue; else return false; } if (!primary_key && s_primary_key.ignore(pos, expected)) { if (expression_p.parse(pos, primary_key, expected)) continue; else return false; } if (!order_by && s_order_by.ignore(pos, expected)) { if (expression_p.parse(pos, order_by, expected)) continue; else return false; } if (!sample_by && s_sample_by.ignore(pos, expected)) { if (expression_p.parse(pos, sample_by, expected)) continue; else return false; } if (!ttl_table && s_ttl.ignore(pos, expected)) { if (parser_ttl_list.parse(pos, ttl_table, expected)) continue; else return false; } if (s_settings.ignore(pos, expected)) { if (!settings_p.parse(pos, settings, expected)) return false; } break; } auto storage = std::make_shared(); storage->set(storage->engine, engine); storage->set(storage->partition_by, partition_by); storage->set(storage->primary_key, primary_key); storage->set(storage->order_by, order_by); storage->set(storage->sample_by, sample_by); storage->set(storage->ttl_table, ttl_table); storage->set(storage->settings, settings); node = storage; return true; } bool ParserCreateTableQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_create("CREATE"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_temporary("TEMPORARY"); ParserKeyword s_table("TABLE"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); ParserCompoundIdentifier table_name_p(true); ParserKeyword s_on("ON"); ParserKeyword s_as("AS"); ParserToken s_dot(TokenType::Dot); ParserToken s_lparen(TokenType::OpeningRoundBracket); ParserToken s_rparen(TokenType::ClosingRoundBracket); ParserStorage storage_p; ParserIdentifier name_p; ParserTablePropertiesDeclarationList table_properties_p; ParserSelectWithUnionQuery select_p; ParserFunction table_function_p; ParserNameList names_p; ASTPtr table; ASTPtr columns_list; ASTPtr storage; ASTPtr as_database; ASTPtr as_table; ASTPtr as_table_function; ASTPtr select; String cluster_str; bool attach = false; bool if_not_exists = false; bool is_temporary = false; if (!s_create.ignore(pos, expected)) { if (s_attach.ignore(pos, expected)) attach = true; else return false; } if (s_temporary.ignore(pos, expected)) { is_temporary = true; } if (!s_table.ignore(pos, expected)) return false; if (s_if_not_exists.ignore(pos, expected)) if_not_exists = true; if (!table_name_p.parse(pos, table, expected)) return false; if (s_on.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } StorageID table_id = getTableIdentifier(table); // Shortcut for ATTACH a previously detached table if (attach && (!pos.isValid() || pos.get().type == TokenType::Semicolon)) { auto query = std::make_shared(); node = query; query->attach = attach; query->if_not_exists = if_not_exists; query->cluster = cluster_str; query->database = table_id.database_name; query->table = table_id.table_name; query->uuid = table_id.uuid; return true; } /// List of columns. if (s_lparen.ignore(pos, expected)) { if (!table_properties_p.parse(pos, columns_list, expected)) return false; if (!s_rparen.ignore(pos, expected)) return false; if (!storage_p.parse(pos, storage, expected) && !is_temporary) return false; } else { storage_p.parse(pos, storage, expected); if (!s_as.ignore(pos, expected)) return false; if (!select_p.parse(pos, select, expected)) /// AS SELECT ... { /// ENGINE can not be specified for table functions. if (storage || !table_function_p.parse(pos, as_table_function, expected)) { /// AS [db.]table if (!name_p.parse(pos, as_table, expected)) return false; if (s_dot.ignore(pos, expected)) { as_database = as_table; if (!name_p.parse(pos, as_table, expected)) return false; } /// Optional - ENGINE can be specified. if (!storage) storage_p.parse(pos, storage, expected); } } } auto query = std::make_shared(); node = query; if (as_table_function) query->as_table_function = as_table_function; query->attach = attach; query->if_not_exists = if_not_exists; query->temporary = is_temporary; query->database = table_id.database_name; query->table = table_id.table_name; query->uuid = table_id.uuid; query->cluster = cluster_str; query->set(query->columns_list, columns_list); query->set(query->storage, storage); tryGetIdentifierNameInto(as_database, query->as_database); tryGetIdentifierNameInto(as_table, query->as_table); query->set(query->select, select); return true; } bool ParserCreateLiveViewQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_create("CREATE"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); ParserCompoundIdentifier table_name_p(true); ParserKeyword s_as("AS"); ParserKeyword s_view("VIEW"); ParserKeyword s_live("LIVE"); ParserToken s_dot(TokenType::Dot); ParserToken s_lparen(TokenType::OpeningRoundBracket); ParserToken s_rparen(TokenType::ClosingRoundBracket); ParserTablePropertiesDeclarationList table_properties_p; ParserSelectWithUnionQuery select_p; ASTPtr table; ASTPtr to_table; ASTPtr columns_list; ASTPtr as_database; ASTPtr as_table; ASTPtr select; ASTPtr live_view_timeout; String cluster_str; bool attach = false; bool if_not_exists = false; if (!s_create.ignore(pos, expected)) { if (s_attach.ignore(pos, expected)) attach = true; else return false; } if (!s_live.ignore(pos, expected)) return false; if (!s_view.ignore(pos, expected)) return false; if (s_if_not_exists.ignore(pos, expected)) if_not_exists = true; if (!table_name_p.parse(pos, table, expected)) return false; if (ParserKeyword{"WITH TIMEOUT"}.ignore(pos, expected)) { if (!ParserNumber{}.parse(pos, live_view_timeout, expected)) live_view_timeout = std::make_shared(static_cast(DEFAULT_TEMPORARY_LIVE_VIEW_TIMEOUT_SEC)); } if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } // TO [db.]table if (ParserKeyword{"TO"}.ignore(pos, expected)) { if (!table_name_p.parse(pos, to_table, expected)) return false; } /// Optional - a list of columns can be specified. It must fully comply with SELECT. if (s_lparen.ignore(pos, expected)) { if (!table_properties_p.parse(pos, columns_list, expected)) return false; if (!s_rparen.ignore(pos, expected)) return false; } /// AS SELECT ... if (!s_as.ignore(pos, expected)) return false; if (!select_p.parse(pos, select, expected)) return false; auto query = std::make_shared(); node = query; query->attach = attach; query->if_not_exists = if_not_exists; query->is_live_view = true; StorageID table_id = getTableIdentifier(table); query->database = table_id.database_name; query->table = table_id.table_name; query->uuid = table_id.uuid; query->cluster = cluster_str; if (to_table) query->to_table_id = getTableIdentifier(to_table); query->set(query->columns_list, columns_list); tryGetIdentifierNameInto(as_database, query->as_database); tryGetIdentifierNameInto(as_table, query->as_table); query->set(query->select, select); if (live_view_timeout) query->live_view_timeout.emplace(live_view_timeout->as().value.safeGet()); return true; } bool ParserCreateDatabaseQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_create("CREATE"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_database("DATABASE"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); ParserStorage storage_p; ParserIdentifier name_p; ASTPtr database; ASTPtr storage; UUID uuid = UUIDHelpers::Nil; String cluster_str; bool attach = false; bool if_not_exists = false; if (!s_create.ignore(pos, expected)) { if (s_attach.ignore(pos, expected)) attach = true; else return false; } if (!s_database.ignore(pos, expected)) return false; if (s_if_not_exists.ignore(pos, expected)) if_not_exists = true; if (!name_p.parse(pos, database, expected)) return false; if (ParserKeyword("UUID").ignore(pos, expected)) { ParserStringLiteral uuid_p; ASTPtr ast_uuid; if (!uuid_p.parse(pos, ast_uuid, expected)) return false; uuid = parseFromString(ast_uuid->as()->value.get()); } if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } storage_p.parse(pos, storage, expected); auto query = std::make_shared(); node = query; query->attach = attach; query->if_not_exists = if_not_exists; tryGetIdentifierNameInto(database, query->database); query->uuid = uuid; query->cluster = cluster_str; query->set(query->storage, storage); return true; } bool ParserCreateViewQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_create("CREATE"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); ParserCompoundIdentifier table_name_p(true); ParserKeyword s_as("AS"); ParserKeyword s_view("VIEW"); ParserKeyword s_materialized("MATERIALIZED"); ParserKeyword s_populate("POPULATE"); ParserKeyword s_or_replace("OR REPLACE"); ParserToken s_dot(TokenType::Dot); ParserToken s_lparen(TokenType::OpeningRoundBracket); ParserToken s_rparen(TokenType::ClosingRoundBracket); ParserStorage storage_p; ParserIdentifier name_p; ParserTablePropertiesDeclarationList table_properties_p; ParserSelectWithUnionQuery select_p; ParserNameList names_p; ASTPtr table; ASTPtr to_table; ASTPtr columns_list; ASTPtr storage; ASTPtr as_database; ASTPtr as_table; ASTPtr select; String cluster_str; bool attach = false; bool if_not_exists = false; bool is_view = false; bool is_materialized_view = false; bool is_populate = false; bool replace_view = false; if (!s_create.ignore(pos, expected)) { if (s_attach.ignore(pos, expected)) attach = true; else return false; } /// VIEW or MATERIALIZED VIEW if (s_or_replace.ignore(pos, expected)) { replace_view = true; } if (!replace_view && s_materialized.ignore(pos, expected)) { is_materialized_view = true; } else is_view = true; if (!s_view.ignore(pos, expected)) return false; if (!replace_view && s_if_not_exists.ignore(pos, expected)) if_not_exists = true; if (!table_name_p.parse(pos, table, expected)) return false; if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } // TO [db.]table if (ParserKeyword{"TO"}.ignore(pos, expected)) { if (!table_name_p.parse(pos, to_table, expected)) return false; } /// Optional - a list of columns can be specified. It must fully comply with SELECT. if (s_lparen.ignore(pos, expected)) { if (!table_properties_p.parse(pos, columns_list, expected)) return false; if (!s_rparen.ignore(pos, expected)) return false; } if (is_materialized_view && !to_table) { /// Internal ENGINE for MATERIALIZED VIEW must be specified. if (!storage_p.parse(pos, storage, expected)) return false; if (s_populate.ignore(pos, expected)) is_populate = true; } /// AS SELECT ... if (!s_as.ignore(pos, expected)) return false; if (!select_p.parse(pos, select, expected)) return false; auto query = std::make_shared(); node = query; query->attach = attach; query->if_not_exists = if_not_exists; query->is_view = is_view; query->is_materialized_view = is_materialized_view; query->is_populate = is_populate; query->replace_view = replace_view; StorageID table_id = getTableIdentifier(table); query->database = table_id.database_name; query->table = table_id.table_name; query->uuid = table_id.uuid; query->cluster = cluster_str; if (to_table) query->to_table_id = getTableIdentifier(to_table); query->set(query->columns_list, columns_list); query->set(query->storage, storage); tryGetIdentifierNameInto(as_database, query->as_database); tryGetIdentifierNameInto(as_table, query->as_table); query->set(query->select, select); return true; } bool ParserCreateDictionaryQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_create("CREATE"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_dictionary("DICTIONARY"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); ParserKeyword s_on("ON"); ParserCompoundIdentifier dict_name_p(true); ParserToken s_left_paren(TokenType::OpeningRoundBracket); ParserToken s_right_paren(TokenType::ClosingRoundBracket); ParserToken s_dot(TokenType::Dot); ParserDictionaryAttributeDeclarationList attributes_p; ParserDictionary dictionary_p; bool if_not_exists = false; ASTPtr name; ASTPtr attributes; ASTPtr dictionary; String cluster_str; bool attach = false; if (!s_create.ignore(pos, expected)) { if (s_attach.ignore(pos, expected)) attach = true; else return false; } if (!s_dictionary.ignore(pos, expected)) return false; if (s_if_not_exists.ignore(pos, expected)) if_not_exists = true; if (!dict_name_p.parse(pos, name, expected)) return false; if (s_on.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } if (!attach) { if (!s_left_paren.ignore(pos, expected)) return false; if (!attributes_p.parse(pos, attributes, expected)) return false; if (!s_right_paren.ignore(pos, expected)) return false; if (!dictionary_p.parse(pos, dictionary, expected)) return false; } auto query = std::make_shared(); node = query; query->is_dictionary = true; query->attach = attach; StorageID dict_id = getTableIdentifier(name); query->database = dict_id.database_name; query->table = dict_id.table_name; query->uuid = dict_id.uuid; query->if_not_exists = if_not_exists; query->set(query->dictionary_attributes_list, attributes); query->set(query->dictionary, dictionary); query->cluster = cluster_str; return true; } bool ParserCreateQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserCreateTableQuery table_p; ParserCreateDatabaseQuery database_p; ParserCreateViewQuery view_p; ParserCreateDictionaryQuery dictionary_p; ParserCreateLiveViewQuery live_view_p; return table_p.parse(pos, node, expected) || database_p.parse(pos, node, expected) || view_p.parse(pos, node, expected) || dictionary_p.parse(pos, node, expected) || live_view_p.parse(pos, node, expected); } }