```
SELECT * FROM t0 ASOF LEFT JOIN t1 ON (t1.x = t0.x) AND greater(('\0llall\0ll\0ll\0llall\0llall\0llall\0llall\0llall\0llall\0llall\0llall\0llall\0llall\0ll\0ll\0llall\0llall\0llall', x, x, y), t0.y, t1.y)
```

{
    if (const auto * ident = ast->as<ASTIdentifier>())
    {
        if (IdentifierSemantic::getColumnName(*ident))
            out.push_back(ident);
        return;
    }
    for (const auto & child : ast->children)
        getIdentifiers(child, out);
}
std::pair<size_t, size_t> CollectJoinOnKeysMatcher::getTableNumbers(const ASTPtr & expr, const ASTPtr & left_ast, const ASTPtr & right_ast,
                                                                    Data & data)
{
    std::vector<const ASTIdentifier *> left_identifiers;
    std::vector<const ASTIdentifier *> right_identifiers;
    getIdentifiers(left_ast, left_identifiers);
    getIdentifiers(right_ast, right_identifiers);
    size_t left_idents_table = getTableForIdentifiers(left_identifiers, data);
    size_t right_idents_table = getTableForIdentifiers(right_identifiers, data);
    if (left_idents_table && left_idents_table == right_idents_table)
    {
        auto left_name = queryToString(*left_identifiers[0]);
        auto right_name = queryToString(*right_identifiers[0]);
        throwSyntaxException("In expression " + queryToString(expr) + " columns " + left_name + " and " + right_name
                                + " are from the same table but from different arguments of equal function.");
    }
    return std::make_pair(left_idents_table, right_idents_table);
}
const ASTIdentifier * CollectJoinOnKeysMatcher::unrollAliases(const ASTIdentifier * identifier, const Aliases & aliases)