1#include <Poco/String.h>
2
3#include <Interpreters/TranslateQualifiedNamesVisitor.h>
4#include <Interpreters/IdentifierSemantic.h>
5#include <Interpreters/AsteriskSemantic.h>
6
7#include <Common/typeid_cast.h>
8#include <Core/Names.h>
9
10#include <Parsers/ASTIdentifier.h>
11#include <Parsers/ASTAsterisk.h>
12#include <Parsers/ASTQualifiedAsterisk.h>
13#include <Parsers/ASTSelectQuery.h>
14#include <Parsers/ASTSelectWithUnionQuery.h>
15#include <Parsers/ASTTablesInSelectQuery.h>
16#include <Parsers/ASTExpressionList.h>
17#include <Parsers/ASTLiteral.h>
18#include <Parsers/ASTFunction.h>
19#include <Parsers/ASTColumnsMatcher.h>
20
21
22namespace DB
23{
24
25namespace ErrorCodes
26{
27 extern const int UNKNOWN_IDENTIFIER;
28 extern const int UNKNOWN_ELEMENT_IN_AST;
29 extern const int LOGICAL_ERROR;
30}
31
32bool TranslateQualifiedNamesMatcher::Data::unknownColumn(size_t table_pos, const ASTIdentifier & identifier) const
33{
34 const auto & table = tables[table_pos].table;
35 auto nested1 = IdentifierSemantic::extractNestedName(identifier, table.table);
36 auto nested2 = IdentifierSemantic::extractNestedName(identifier, table.alias);
37
38 String short_name = identifier.shortName();
39 const Names & column_names = tables[table_pos].columns;
40 for (auto & known_name : column_names)
41 {
42 if (short_name == known_name)
43 return false;
44 if (nested1 && *nested1 == known_name)
45 return false;
46 if (nested2 && *nested2 == known_name)
47 return false;
48 }
49
50 const Names & hidden_names = tables[table_pos].hidden_columns;
51 for (auto & known_name : hidden_names)
52 {
53 if (short_name == known_name)
54 return false;
55 if (nested1 && *nested1 == known_name)
56 return false;
57 if (nested2 && *nested2 == known_name)
58 return false;
59 }
60
61 return !column_names.empty();
62}
63
64bool TranslateQualifiedNamesMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child)
65{
66 /// Do not go to FROM, JOIN, subqueries.
67 if (child->as<ASTTableExpression>() || child->as<ASTSelectWithUnionQuery>())
68 return false;
69
70 /// Processed nodes. Do not go into children.
71 if (node->as<ASTQualifiedAsterisk>() || node->as<ASTTableJoin>())
72 return false;
73
74 /// ASTSelectQuery + others
75 return true;
76}
77
78void TranslateQualifiedNamesMatcher::visit(ASTPtr & ast, Data & data)
79{
80 if (auto * t = ast->as<ASTIdentifier>())
81 visit(*t, ast, data);
82 if (auto * t = ast->as<ASTTableJoin>())
83 visit(*t, ast, data);
84 if (auto * t = ast->as<ASTSelectQuery>())
85 visit(*t, ast, data);
86 if (auto * node = ast->as<ASTExpressionList>())
87 visit(*node, ast, data);
88 if (auto * node = ast->as<ASTFunction>())
89 visit(*node, ast, data);
90}
91
92void TranslateQualifiedNamesMatcher::visit(ASTIdentifier & identifier, ASTPtr &, Data & data)
93{
94 if (IdentifierSemantic::getColumnName(identifier))
95 {
96 String short_name = identifier.shortName();
97 size_t table_pos = 0;
98 bool allow_ambiguous = data.join_using_columns.count(short_name);
99 if (IdentifierSemantic::chooseTable(identifier, data.tables, table_pos, allow_ambiguous))
100 {
101 if (data.unknownColumn(table_pos, identifier))
102 {
103 String table_name = data.tables[table_pos].table.getQualifiedNamePrefix(false);
104 throw Exception("There's no column '" + identifier.name + "' in table '" + table_name + "'",
105 ErrorCodes::UNKNOWN_IDENTIFIER);
106 }
107
108 IdentifierSemantic::setMembership(identifier, table_pos);
109
110 /// In case if column from the joined table are in source columns, change it's name to qualified.
111 auto & table = data.tables[table_pos].table;
112 if (table_pos && data.hasColumn(short_name))
113 IdentifierSemantic::setColumnLongName(identifier, table);
114 else
115 IdentifierSemantic::setColumnShortName(identifier, table);
116 }
117 }
118}
119
120/// As special case, treat count(*) as count(), not as count(list of all columns).
121void TranslateQualifiedNamesMatcher::visit(ASTFunction & node, const ASTPtr &, Data &)
122{
123 ASTPtr & func_arguments = node.arguments;
124
125 String func_name_lowercase = Poco::toLower(node.name);
126 if (func_name_lowercase == "count" &&
127 func_arguments->children.size() == 1 &&
128 func_arguments->children[0]->as<ASTAsterisk>())
129 func_arguments->children.clear();
130}
131
132void TranslateQualifiedNamesMatcher::visit(const ASTQualifiedAsterisk & , const ASTPtr & ast, Data & data)
133{
134 if (ast->children.size() != 1)
135 throw Exception("Logical error: qualified asterisk must have exactly one child", ErrorCodes::LOGICAL_ERROR);
136
137 auto & ident = ast->children[0];
138
139 /// @note it could contain table alias as table name.
140 DatabaseAndTableWithAlias db_and_table(ident);
141
142 for (const auto & known_table : data.tables)
143 if (db_and_table.satisfies(known_table.table, true))
144 return;
145
146 throw Exception("Unknown qualified identifier: " + ident->getAliasOrColumnName(), ErrorCodes::UNKNOWN_IDENTIFIER);
147}
148
149void TranslateQualifiedNamesMatcher::visit(ASTTableJoin & join, const ASTPtr & , Data & data)
150{
151 if (join.using_expression_list)
152 Visitor(data).visit(join.using_expression_list);
153 else if (join.on_expression)
154 Visitor(data).visit(join.on_expression);
155}
156
157void TranslateQualifiedNamesMatcher::visit(ASTSelectQuery & select, const ASTPtr & , Data & data)
158{
159 if (auto join = select.join())
160 extractJoinUsingColumns(join->table_join, data);
161
162 /// If the WHERE clause or HAVING consists of a single qualified column, the reference must be translated not only in children,
163 /// but also in where_expression and having_expression.
164 if (select.prewhere())
165 Visitor(data).visit(select.refPrewhere());
166 if (select.where())
167 Visitor(data).visit(select.refWhere());
168 if (select.having())
169 Visitor(data).visit(select.refHaving());
170}
171
172static void addIdentifier(ASTs & nodes, const DatabaseAndTableWithAlias & table, const String & column_name,
173 AsteriskSemantic::RevertedAliasesPtr aliases)
174{
175 String table_name = table.getQualifiedNamePrefix(false);
176 auto identifier = std::make_shared<ASTIdentifier>(std::vector<String>{table_name, column_name});
177
178 bool added = false;
179 if (aliases && aliases->count(identifier->name))
180 {
181 for (const String & alias : (*aliases)[identifier->name])
182 {
183 nodes.push_back(identifier->clone());
184 nodes.back()->setAlias(alias);
185 added = true;
186 }
187 }
188
189 if (!added)
190 nodes.emplace_back(identifier);
191}
192
193/// Replace *, alias.*, database.table.* with a list of columns.
194void TranslateQualifiedNamesMatcher::visit(ASTExpressionList & node, const ASTPtr &, Data & data)
195{
196 const auto & tables_with_columns = data.tables;
197
198 ASTs old_children;
199 if (data.processAsterisks())
200 {
201 bool has_asterisk = false;
202 for (const auto & child : node.children)
203 {
204 if (child->as<ASTAsterisk>() || child->as<ASTColumnsMatcher>())
205 {
206 if (tables_with_columns.empty())
207 throw Exception("An asterisk cannot be replaced with empty columns.", ErrorCodes::LOGICAL_ERROR);
208 has_asterisk = true;
209 break;
210 }
211 else if (const auto * qa = child->as<ASTQualifiedAsterisk>())
212 {
213 visit(*qa, child, data); /// check if it's OK before rewrite
214 has_asterisk = true;
215 break;
216 }
217 }
218
219 if (has_asterisk)
220 {
221 old_children.swap(node.children);
222 node.children.reserve(old_children.size());
223 }
224 }
225
226 for (const auto & child : old_children)
227 {
228 if (const auto * asterisk = child->as<ASTAsterisk>())
229 {
230 bool first_table = true;
231 for (const auto & table : tables_with_columns)
232 {
233 for (const auto & column_name : table.columns)
234 {
235 if (first_table || !data.join_using_columns.count(column_name))
236 {
237 addIdentifier(node.children, table.table, column_name, AsteriskSemantic::getAliases(*asterisk));
238 }
239 }
240
241 first_table = false;
242 }
243 }
244 else if (const auto * asterisk_pattern = child->as<ASTColumnsMatcher>())
245 {
246 bool first_table = true;
247 for (const auto & table : tables_with_columns)
248 {
249 for (const auto & column_name : table.columns)
250 {
251 if (asterisk_pattern->isColumnMatching(column_name) && (first_table || !data.join_using_columns.count(column_name)))
252 {
253 addIdentifier(node.children, table.table, column_name, AsteriskSemantic::getAliases(*asterisk_pattern));
254 }
255 }
256
257 first_table = false;
258 }
259 }
260 else if (const auto * qualified_asterisk = child->as<ASTQualifiedAsterisk>())
261 {
262 DatabaseAndTableWithAlias ident_db_and_name(qualified_asterisk->children[0]);
263
264 for (const auto & table : tables_with_columns)
265 {
266 if (ident_db_and_name.satisfies(table.table, true))
267 {
268 for (const auto & column_name : table.columns)
269 {
270 addIdentifier(node.children, table.table, column_name, AsteriskSemantic::getAliases(*qualified_asterisk));
271 }
272 break;
273 }
274 }
275 }
276 else
277 node.children.emplace_back(child);
278 }
279}
280
281/// 'select * from a join b using id' should result one 'id' column
282void TranslateQualifiedNamesMatcher::extractJoinUsingColumns(const ASTPtr ast, Data & data)
283{
284 const auto & table_join = ast->as<ASTTableJoin &>();
285
286 if (table_join.using_expression_list)
287 {
288 const auto & keys = table_join.using_expression_list->as<ASTExpressionList &>();
289 for (const auto & key : keys.children)
290 if (auto opt_column = tryGetIdentifierName(key))
291 data.join_using_columns.insert(*opt_column);
292 else if (key->as<ASTLiteral>())
293 data.join_using_columns.insert(key->getColumnName());
294 else
295 {
296 String alias = key->tryGetAlias();
297 if (alias.empty())
298 throw Exception("Logical error: expected identifier or alias, got: " + key->getID(), ErrorCodes::LOGICAL_ERROR);
299 data.join_using_columns.insert(alias);
300 }
301 }
302}
303
304void RestoreQualifiedNamesData::visit(ASTIdentifier & identifier, ASTPtr & ast)
305{
306 if (IdentifierSemantic::getColumnName(identifier))
307 {
308 if (IdentifierSemantic::getMembership(identifier))
309 {
310 ast = identifier.clone();
311 ast->as<ASTIdentifier>()->restoreCompoundName();
312 }
313 }
314}
315
316}
317