1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#include <Interpreters/MarkTableIdentifiersVisitor.h>
#include <IO/WriteBufferFromOStream.h>
#include <Interpreters/IdentifierSemantic.h>
#include <Interpreters/misc.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTTablesInSelectQuery.h>
namespace DB
{
namespace
{
void replaceArgumentWithTableIdentifierIfNotAlias(ASTFunction & func, size_t argument_pos, const Aliases & aliases)
{
if (!func.arguments || (func.arguments->children.size() <= argument_pos))
return;
auto arg = func.arguments->children[argument_pos];
auto * identifier = arg->as<ASTIdentifier>();
if (!identifier)
return;
if (aliases.contains(identifier->name()))
return;
auto table_identifier = identifier->createTable();
if (!table_identifier)
return;
func.arguments->children[argument_pos] = table_identifier;
}
}
bool MarkTableIdentifiersMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child)
{
if (child->as<ASTSelectQuery>())
return false;
if (node->as<ASTTableExpression>())
return false;
return true;
}
void MarkTableIdentifiersMatcher::visit(ASTPtr & ast, Data & data)
{
if (auto * node_func = ast->as<ASTFunction>())
visit(*node_func, data);
}
void MarkTableIdentifiersMatcher::visit(ASTFunction & func, const Data & data)
{
/// `IN t` can be specified, where t is a table, which is equivalent to `IN (SELECT * FROM t)`.
if (checkFunctionIsInOrGlobalInOperator(func))
{
replaceArgumentWithTableIdentifierIfNotAlias(func, 1, data.aliases);
}
// First argument of joinGet can be a table name, perhaps with a database.
// First argument of dictGet can be a dictionary name, perhaps with a database.
else if (functionIsJoinGet(func.name) || functionIsDictGet(func.name))
{
replaceArgumentWithTableIdentifierIfNotAlias(func, 0, data.aliases);
}
}
}
|