#include #include #include namespace DB { bool ColumnNamesContext::addTableAliasIfAny(const IAST & ast) { String alias = ast.tryGetAlias(); if (alias.empty()) return false; table_aliases.insert(alias); return true; } bool ColumnNamesContext::addColumnAliasIfAny(const IAST & ast) { String alias = ast.tryGetAlias(); if (alias.empty()) return false; if (required_names.count(alias)) masked_columns.insert(alias); complex_aliases.insert(alias); return true; } void ColumnNamesContext::addColumnIdentifier(const ASTIdentifier & node) { if (!IdentifierSemantic::getColumnName(node)) return; /// There should be no complex cases after query normalization. Names to aliases: one-to-many. String alias = node.tryGetAlias(); required_names[node.name].addInclusion(alias); } bool ColumnNamesContext::addArrayJoinAliasIfAny(const IAST & ast) { String alias = ast.tryGetAlias(); if (alias.empty()) return false; array_join_columns.insert(alias); return true; } void ColumnNamesContext::addArrayJoinIdentifier(const ASTIdentifier & node) { array_join_columns.insert(node.name); } size_t ColumnNamesContext::nameInclusion(const String & name) const { auto it = required_names.find(name); if (it != required_names.end()) return it->second.appears; return 0; } NameSet ColumnNamesContext::requiredColumns() const { NameSet required; for (const auto & pr : required_names) { const auto & name = pr.first; String table_name = Nested::extractTableName(name); /// Tech debt. There's its own logic for ARRAY JOIN columns. if (array_join_columns.count(name) || array_join_columns.count(table_name)) continue; if (!complex_aliases.count(name) || masked_columns.count(name)) required.insert(name); } return required; } std::ostream & operator << (std::ostream & os, const ColumnNamesContext & cols) { os << "required_names: "; for (const auto & pr : cols.required_names) { os << "'" << pr.first << "'"; for (auto & alias : pr.second.aliases) os << "/'" << alias << "'"; } os << " source_tables: "; for (const auto & x : cols.tables) { auto alias = x.alias(); auto name = x.name(); if (alias && name) os << "'" << *alias << "'/'" << *name << "' "; else if (alias) os << "'" << *alias << "' "; else if (name) os << "'" << *name << "' "; } os << "table_aliases: "; for (const auto & x : cols.table_aliases) os << "'" << x << "' "; os << "complex_aliases: "; for (const auto & x : cols.complex_aliases) os << "'" << x << "' "; os << "masked_columns: "; for (const auto & x : cols.masked_columns) os << "'" << x << "' "; os << "array_join_columns: "; for (const auto & x : cols.array_join_columns) os << "'" << x << "' "; return os; } }