#include #include #include #include #include #include #include #include namespace DB { /// Checks that ast is ASTIdentifier and remove num_qualifiers_to_strip components from left. /// Example: 'database.table.name' -> (num_qualifiers_to_strip = 2) -> 'name'. void stripIdentifier(const DB::ASTPtr & ast, size_t num_qualifiers_to_strip) { ASTIdentifier * identifier = typeid_cast(ast.get()); if (!identifier) throw DB::Exception("ASTIdentifier expected for stripIdentifier", DB::ErrorCodes::LOGICAL_ERROR); if (num_qualifiers_to_strip) { identifier->name_parts.erase(identifier->name_parts.begin(), identifier->name_parts.begin() + num_qualifiers_to_strip); DB::String new_name; for (const auto & part : identifier->name_parts) { if (!new_name.empty()) new_name += '.'; new_name += part; } identifier->name.swap(new_name); } } /// Get the number of components of identifier which are correspond to 'alias.', 'table.' or 'databas.table.' from names. size_t getNumComponentsToStripInOrderToTranslateQualifiedName(const ASTIdentifier & identifier, const DatabaseAndTableWithAlias & names) { /// database.table.column if (doesIdentifierBelongTo(identifier, names.database, names.table)) return 2; /// table.column or alias.column. if (doesIdentifierBelongTo(identifier, names.table) || doesIdentifierBelongTo(identifier, names.alias)) return 1; return 0; } DatabaseAndTableWithAlias::DatabaseAndTableWithAlias(const ASTIdentifier & identifier, const String & current_database) { database = current_database; table = identifier.name; alias = identifier.tryGetAlias(); if (!identifier.name_parts.empty()) { if (identifier.name_parts.size() != 2) throw Exception("Logical error: 2 components expected in table expression '" + identifier.name + "'", ErrorCodes::LOGICAL_ERROR); database = identifier.name_parts[0]; table = identifier.name_parts[1]; } } DatabaseAndTableWithAlias::DatabaseAndTableWithAlias(const ASTPtr & node, const String & current_database) { const auto * identifier = typeid_cast(node.get()); if (!identifier) throw Exception("Logical error: identifier expected", ErrorCodes::LOGICAL_ERROR); *this = DatabaseAndTableWithAlias(*identifier, current_database); } DatabaseAndTableWithAlias::DatabaseAndTableWithAlias(const ASTTableExpression & table_expression, const String & current_database) { if (table_expression.database_and_table_name) *this = DatabaseAndTableWithAlias(table_expression.database_and_table_name, current_database); else if (table_expression.table_function) alias = table_expression.table_function->tryGetAlias(); else if (table_expression.subquery) alias = table_expression.subquery->tryGetAlias(); else throw Exception("Logical error: no known elements in ASTTableExpression", ErrorCodes::LOGICAL_ERROR); } bool DatabaseAndTableWithAlias::satisfies(const DatabaseAndTableWithAlias & db_table, bool table_may_be_an_alias) { /// table.*, alias.* or database.table.* if (database.empty()) { if (!db_table.table.empty() && table == db_table.table) return true; if (!db_table.alias.empty()) return (alias == db_table.alias) || (table_may_be_an_alias && table == db_table.alias); } return database == db_table.database && table == db_table.table; } String DatabaseAndTableWithAlias::getQualifiedNamePrefix() const { if (alias.empty() && table.empty()) return ""; return (!alias.empty() ? alias : (database + '.' + table)) + '.'; } void DatabaseAndTableWithAlias::makeQualifiedName(const ASTPtr & ast) const { if (auto identifier = typeid_cast(ast.get())) { String prefix = getQualifiedNamePrefix(); identifier->name.insert(identifier->name.begin(), prefix.begin(), prefix.end()); addIdentifierQualifier(*identifier, database, table, alias); } } std::vector getSelectTablesExpression(const ASTSelectQuery & select_query) { if (!select_query.tables) return {}; std::vector tables_expression; for (const auto & child : select_query.tables->children) { ASTTablesInSelectQueryElement * tables_element = static_cast(child.get()); if (tables_element->table_expression) tables_expression.emplace_back(static_cast(tables_element->table_expression.get())); } return tables_expression; } static const ASTTableExpression * getTableExpression(const ASTSelectQuery & select, size_t table_number) { if (!select.tables) return {}; ASTTablesInSelectQuery & tables_in_select_query = static_cast(*select.tables); if (tables_in_select_query.children.size() <= table_number) return {}; ASTTablesInSelectQueryElement & tables_element = static_cast(*tables_in_select_query.children[table_number]); if (!tables_element.table_expression) return {}; return static_cast(tables_element.table_expression.get()); } std::vector getDatabaseAndTables(const ASTSelectQuery & select_query, const String & current_database) { std::vector tables_expression = getSelectTablesExpression(select_query); std::vector database_and_table_with_aliases; database_and_table_with_aliases.reserve(tables_expression.size()); for (const auto & table_expression : tables_expression) database_and_table_with_aliases.emplace_back(DatabaseAndTableWithAlias(*table_expression, current_database)); return database_and_table_with_aliases; } std::optional getDatabaseAndTable(const ASTSelectQuery & select, size_t table_number) { const ASTTableExpression * table_expression = getTableExpression(select, table_number); if (!table_expression) return {}; ASTPtr database_and_table_name = table_expression->database_and_table_name; if (!database_and_table_name || !isIdentifier(database_and_table_name)) return {}; return DatabaseAndTableWithAlias(database_and_table_name); } ASTPtr extractTableExpression(const ASTSelectQuery & select, size_t table_number) { if (const ASTTableExpression * table_expression = getTableExpression(select, table_number)) { if (table_expression->database_and_table_name) return table_expression->database_and_table_name; if (table_expression->table_function) return table_expression->table_function; if (table_expression->subquery) return static_cast(table_expression->subquery.get())->children[0]; } return nullptr; } }