#include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int UNEXPECTED_AST_STRUCTURE; extern const int SYNTAX_ERROR; } ASTIdentifier::ASTIdentifier(const String & short_name, ASTPtr && name_param) : full_name(short_name), name_parts{short_name}, semantic(std::make_shared()) { if (name_param == nullptr) assert(!full_name.empty()); else children.push_back(std::move(name_param)); } ASTIdentifier::ASTIdentifier(std::vector && name_parts_, bool special, std::vector && name_params) : name_parts(name_parts_), semantic(std::make_shared()) { assert(!name_parts.empty()); semantic->special = special; semantic->legacy_compound = true; if (!name_params.empty()) { size_t params = 0; for (const auto & part [[maybe_unused]] : name_parts) { if (part.empty()) ++params; } assert(params == name_params.size()); children = std::move(name_params); } else { for (const auto & part [[maybe_unused]] : name_parts) assert(!part.empty()); if (!special && name_parts.size() >= 2) semantic->table = name_parts.end()[-2]; resetFullName(); } } ASTPtr ASTIdentifier::getParam() const { assert(full_name.empty() && children.size() == 1); return children.front()->clone(); } ASTPtr ASTIdentifier::clone() const { auto ret = std::make_shared(*this); ret->semantic = std::make_shared(*ret->semantic); return ret; } bool ASTIdentifier::supposedToBeCompound() const { return semantic->legacy_compound; } void ASTIdentifier::setShortName(const String & new_name) { assert(!new_name.empty()); full_name = new_name; name_parts = {new_name}; bool special = semantic->special; *semantic = IdentifierSemanticImpl(); semantic->special = special; } const String & ASTIdentifier::name() const { if (children.empty()) { assert(!name_parts.empty()); assert(!full_name.empty()); } return full_name; } void ASTIdentifier::formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const { auto format_element = [&](const String & elem_name) { settings.ostr << (settings.hilite ? hilite_identifier : ""); settings.writeIdentifier(elem_name); settings.ostr << (settings.hilite ? hilite_none : ""); }; /// It could be compound but short if (!isShort()) { for (size_t i = 0, j = 0, size = name_parts.size(); i < size; ++i) { if (i != 0) settings.ostr << '.'; if (name_parts[i].empty()) children[j++]->formatImpl(settings, state, frame); else format_element(name_parts[i]); } } else { const auto & name = shortName(); if (name.empty()) children.front()->formatImpl(settings, state, frame); else format_element(name); } } void ASTIdentifier::appendColumnNameImpl(WriteBuffer & ostr) const { writeString(name(), ostr); } void ASTIdentifier::restoreTable() { if (!compound()) { name_parts.insert(name_parts.begin(), semantic->table); resetFullName(); } } void ASTIdentifier::resetFullName() { full_name = name_parts[0]; for (size_t i = 1; i < name_parts.size(); ++i) full_name += '.' + name_parts[i]; } ASTTableIdentifier::ASTTableIdentifier(const String & table_name) : ASTIdentifier({table_name}, true) { } ASTTableIdentifier::ASTTableIdentifier(const StorageID & table_id) : ASTIdentifier( table_id.database_name.empty() ? std::vector{table_id.table_name} : std::vector{table_id.database_name, table_id.table_name}, true) { uuid = table_id.uuid; } ASTTableIdentifier::ASTTableIdentifier(const String & database_name, const String & table_name) : ASTIdentifier({database_name, table_name}, true) { } ASTPtr ASTTableIdentifier::clone() const { auto ret = std::make_shared(*this); ret->semantic = std::make_shared(*ret->semantic); return ret; } StorageID ASTTableIdentifier::getTableId() const { if (name_parts.size() == 2) return {name_parts[0], name_parts[1], uuid}; else return {{}, name_parts[0], uuid}; } void ASTTableIdentifier::resetTable(const String & database_name, const String & table_name) { auto identifier = std::make_shared(database_name, table_name); full_name.swap(identifier->full_name); name_parts.swap(identifier->name_parts); uuid = identifier->uuid; } void ASTTableIdentifier::updateTreeHashImpl(SipHash & hash_state) const { hash_state.update(uuid); IAST::updateTreeHashImpl(hash_state); } String getIdentifierName(const IAST * ast) { String res; if (tryGetIdentifierNameInto(ast, res)) return res; throw Exception(ast ? queryToString(*ast) + " is not an identifier" : "AST node is nullptr", ErrorCodes::UNEXPECTED_AST_STRUCTURE); } std::optional tryGetIdentifierName(const IAST * ast) { String res; if (tryGetIdentifierNameInto(ast, res)) return res; return {}; } bool tryGetIdentifierNameInto(const IAST * ast, String & name) { if (ast) { if (const auto * node = ast->as()) { name = node->name(); return true; } } return false; } void setIdentifierSpecial(ASTPtr & ast) { if (ast) if (auto * id = ast->as()) id->semantic->special = true; } }