#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) { ParserFunction function_or_array; if (function_or_array.parse(pos, node, expected)) return true; ParserNestedTable nested; if (nested.parse(pos, node, expected)) return true; return false; } 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; ParserIdentifierWithOptionalParameters ident_with_optional_params_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 (!ident_with_optional_params_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; 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_temporary("TEMPORARY"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_table("TABLE"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); 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 database; ASTPtr table; ASTPtr columns_list; ASTPtr to_database; ASTPtr to_table; 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 (!name_p.parse(pos, table, expected)) return false; if (s_dot.ignore(pos, expected)) { database = table; if (!name_p.parse(pos, table, expected)) return false; } if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } // 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; tryGetIdentifierNameInto(database, query->database); tryGetIdentifierNameInto(table, query->table); 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 ... { if (!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; tryGetIdentifierNameInto(database, query->database); tryGetIdentifierNameInto(table, query->table); query->cluster = cluster_str; tryGetIdentifierNameInto(to_database, query->to_database); tryGetIdentifierNameInto(to_table, query->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 ParserCreateLiveViewQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_create("CREATE"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); 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); ParserStorage storage_p; ParserIdentifier name_p; ParserTablePropertiesDeclarationList table_properties_p; ParserSelectWithUnionQuery select_p; ASTPtr database; ASTPtr table; ASTPtr columns_list; ASTPtr to_database; ASTPtr to_table; ASTPtr storage; 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 (!name_p.parse(pos, table, expected)) return false; if (s_dot.ignore(pos, expected)) { database = table; if (!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 (!name_p.parse(pos, to_table, expected)) return false; if (s_dot.ignore(pos, expected)) { to_database = to_table; if (!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; tryGetIdentifierNameInto(database, query->database); tryGetIdentifierNameInto(table, query->table); query->cluster = cluster_str; tryGetIdentifierNameInto(to_database, query->to_database); tryGetIdentifierNameInto(to_table, query->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 ParserCreateWindowViewQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_create("CREATE"); ParserKeyword s_temporary("TEMPORARY"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); ParserKeyword s_as("AS"); ParserKeyword s_view("VIEW"); ParserKeyword s_window("WINDOW"); 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; ASTPtr database; ASTPtr table; ASTPtr columns_list; ASTPtr to_database; ASTPtr to_table; ASTPtr storage; ASTPtr as_database; ASTPtr as_table; 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_window.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 (!name_p.parse(pos, table, expected)) return false; if (s_dot.ignore(pos, expected)) { database = table; if (!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 (!name_p.parse(pos, to_table, expected)) return false; if (s_dot.ignore(pos, expected)) { to_database = to_table; if (!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_window_view = true; query->temporary = is_temporary; tryGetIdentifierNameInto(database, query->database); tryGetIdentifierNameInto(table, query->table); query->cluster = cluster_str; tryGetIdentifierNameInto(to_database, query->to_database); tryGetIdentifierNameInto(to_table, query->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); 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; 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{"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->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"); 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 database; ASTPtr table; ASTPtr columns_list; ASTPtr to_database; ASTPtr to_table; 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 (!name_p.parse(pos, table, expected)) return false; if (s_dot.ignore(pos, expected)) { database = table; if (!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 (!name_p.parse(pos, to_table, expected)) return false; if (s_dot.ignore(pos, expected)) { to_database = to_table; if (!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; tryGetIdentifierNameInto(database, query->database); tryGetIdentifierNameInto(table, query->table); query->cluster = cluster_str; tryGetIdentifierNameInto(to_database, query->to_database); tryGetIdentifierNameInto(to_table, query->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"); ParserIdentifier name_p; 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 database; 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 (!name_p.parse(pos, name, expected)) return false; if (s_dot.ignore(pos)) { database = name; if (!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; if (database) query->database = typeid_cast(*database).name; query->table = typeid_cast(*name).name; 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; ParserCreateWindowViewQuery window_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) || window_view_p.parse(pos, node, expected); } }