Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some more ASTIdentifier refactoring #4077

Merged
merged 4 commits into from Jan 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 6 additions & 8 deletions dbms/src/Interpreters/ActionsVisitor.cpp
Expand Up @@ -446,13 +446,11 @@ void ActionsVisitor::visit(const ASTPtr & ast)

for (size_t j = 0; j < lambda_arg_asts.size(); ++j)
{
ASTIdentifier * lambda_identifier = typeid_cast<ASTIdentifier *>(lambda_arg_asts[j].get());
if (!lambda_identifier)
auto opt_arg_name = getIdentifierName(lambda_arg_asts[j]);
if (!opt_arg_name)
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);

String arg_name = lambda_identifier->name;

lambda_arguments.emplace_back(arg_name, lambda_type->getArgumentTypes()[j]);
lambda_arguments.emplace_back(*opt_arg_name, lambda_type->getArgumentTypes()[j]);
}

actions_stack.pushLevel(lambda_arguments);
Expand Down Expand Up @@ -541,9 +539,6 @@ void ActionsVisitor::makeSet(const ASTFunction * node, const Block & sample_bloc
const ASTIdentifier * identifier = typeid_cast<const ASTIdentifier *>(arg.get());
if (typeid_cast<const ASTSubquery *>(arg.get()) || identifier)
{
/// We get the stream of blocks for the subquery. Create Set and put it in place of the subquery.
String set_id = arg->getColumnName();

/// A special case is if the name of the table is specified on the right side of the IN statement,
/// and the table has the type Set (a previously prepared set).
if (identifier)
Expand All @@ -563,6 +558,9 @@ void ActionsVisitor::makeSet(const ASTFunction * node, const Block & sample_bloc
}
}

/// We get the stream of blocks for the subquery. Create Set and put it in place of the subquery.
String set_id = arg->getColumnName();

SubqueryForSet & subquery_for_set = subqueries_for_sets[set_id];

/// If you already created a Set with the same subquery / table.
Expand Down
10 changes: 4 additions & 6 deletions dbms/src/Interpreters/AddDefaultDatabaseVisitor.h
Expand Up @@ -10,6 +10,7 @@
#include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/DumpASTNode.h>
#include <Interpreters/DatabaseAndTableWithAlias.h>

namespace DB
{
Expand Down Expand Up @@ -90,19 +91,16 @@ class AddDefaultDatabaseVisitor
void visit(ASTTableExpression & table_expression, ASTPtr &) const
{
if (table_expression.database_and_table_name)
{
tryVisit<ASTIdentifier>(table_expression.database_and_table_name);

if (table_expression.database_and_table_name->children.size() != 2)
throw Exception("Logical error: more than two components in table expression", ErrorCodes::LOGICAL_ERROR);
}
else if (table_expression.subquery)
tryVisit<ASTSubquery>(table_expression.subquery);
}

/// @note It expects that only table (not column) identifiers are visited.
void visit(const ASTIdentifier & identifier, ASTPtr & ast) const
{
if (ast->children.empty())
DatabaseAndTableWithAlias db_and_name(identifier);
if (db_and_name.database.empty())
ast = createTableIdentifier(database_name, identifier.name);
}

Expand Down
74 changes: 28 additions & 46 deletions dbms/src/Interpreters/DatabaseAndTableWithAlias.cpp
Expand Up @@ -52,32 +52,16 @@ void stripIdentifier(DB::ASTPtr & ast, size_t num_qualifiers_to_strip)
size_t getNumComponentsToStripInOrderToTranslateQualifiedName(const ASTIdentifier & identifier,
const DatabaseAndTableWithAlias & names)
{
size_t num_qualifiers_to_strip = 0;
/// database.table.column
if (doesIdentifierBelongTo(identifier, names.database, names.table))
return 2;

/// It is compound identifier
if (!identifier.children.empty())
{
size_t num_components = identifier.children.size();

/// database.table.column
if (num_components >= 3
&& !names.database.empty()
&& *getIdentifierName(identifier.children[0]) == names.database
&& *getIdentifierName(identifier.children[1]) == names.table)
{
num_qualifiers_to_strip = 2;
}

/// table.column or alias.column. If num_components > 2, it is like table.nested.column.
if (num_components >= 2
&& ((!names.table.empty() && *getIdentifierName(identifier.children[0]) == names.table)
|| (!names.alias.empty() && *getIdentifierName(identifier.children[0]) == names.alias)))
{
num_qualifiers_to_strip = 1;
}
}
/// table.column or alias.column.
if (doesIdentifierBelongTo(identifier, names.table) ||
doesIdentifierBelongTo(identifier, names.alias))
return 1;

return num_qualifiers_to_strip;
return 0;
}


Expand Down Expand Up @@ -118,6 +102,22 @@ DatabaseAndTableWithAlias::DatabaseAndTableWithAlias(const ASTTableExpression &
throw Exception("Logical error: no known elements in ASTTableExpression", ErrorCodes::LOGICAL_ERROR);
}

bool DatabaseAndTableWithAlias::satisfies(const DatabaseAndTableWithAlias & db_table, bool table_may_be_an_alias)
{
/// table.*, alias.* or database.table.*

if (database.empty())
{
if (!db_table.table.empty() && table == db_table.table)
return true;

if (!db_table.alias.empty())
return (alias == db_table.alias) || (table_may_be_an_alias && table == db_table.alias);
}

return database == db_table.database && table == db_table.table;
}

String DatabaseAndTableWithAlias::getQualifiedNamePrefix() const
{
if (alias.empty() && table.empty())
Expand All @@ -133,17 +133,7 @@ void DatabaseAndTableWithAlias::makeQualifiedName(const ASTPtr & ast) const
String prefix = getQualifiedNamePrefix();
identifier->name.insert(identifier->name.begin(), prefix.begin(), prefix.end());

Names qualifiers;
if (!alias.empty())
qualifiers.push_back(alias);
else
{
qualifiers.push_back(database);
qualifiers.push_back(table);
}

for (const auto & qualifier : qualifiers)
identifier->children.emplace_back(std::make_shared<ASTIdentifier>(qualifier));
addIdentifierQualifier(*identifier, database, table, alias);
}
}

Expand Down Expand Up @@ -209,21 +199,13 @@ std::optional<DatabaseAndTableWithAlias> getDatabaseAndTable(const ASTSelectQuer
return DatabaseAndTableWithAlias(database_and_table_name);
}

ASTPtr getTableFunctionOrSubquery(const ASTSelectQuery & select, size_t table_number)
ASTPtr extractTableExpression(const ASTSelectQuery & select, size_t table_number)
{
const ASTTableExpression * table_expression = getTableExpression(select, table_number);
if (table_expression)
if (const ASTTableExpression * table_expression = getTableExpression(select, table_number))
{
#if 1 /// TODO: It hides some logical error in InterpreterSelectQuery & distributed tables
if (table_expression->database_and_table_name)
{
if (table_expression->database_and_table_name->children.empty())
return table_expression->database_and_table_name;
return table_expression->database_and_table_name;

if (table_expression->database_and_table_name->children.size() == 2)
return table_expression->database_and_table_name->children[1];
}
#endif
if (table_expression->table_function)
return table_expression->table_function;

Expand Down
8 changes: 6 additions & 2 deletions dbms/src/Interpreters/DatabaseAndTableWithAlias.h
Expand Up @@ -2,8 +2,9 @@

#include <memory>
#include <optional>

#include <Core/Types.h>
#include <Parsers/ASTSelectQuery.h>


namespace DB
{
Expand Down Expand Up @@ -33,6 +34,9 @@ struct DatabaseAndTableWithAlias

/// If ast is ASTIdentifier, prepend getQualifiedNamePrefix() to it's name.
void makeQualifiedName(const ASTPtr & ast) const;

/// Check if it satisfies another db_table name. @note opterion is not symmetric.
bool satisfies(const DatabaseAndTableWithAlias & table, bool table_may_be_an_alias);
};

void stripIdentifier(DB::ASTPtr & ast, size_t num_qualifiers_to_strip);
Expand All @@ -44,6 +48,6 @@ std::vector<DatabaseAndTableWithAlias> getDatabaseAndTables(const ASTSelectQuery
std::optional<DatabaseAndTableWithAlias> getDatabaseAndTable(const ASTSelectQuery & select, size_t table_number);

std::vector<const ASTTableExpression *> getSelectTablesExpression(const ASTSelectQuery & select_query);
ASTPtr getTableFunctionOrSubquery(const ASTSelectQuery & select, size_t table_number);
ASTPtr extractTableExpression(const ASTSelectQuery & select, size_t table_number);

}
1 change: 1 addition & 0 deletions dbms/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp
@@ -1,6 +1,7 @@
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ASTSubquery.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/ASTExpressionList.h>

Expand Down
2 changes: 1 addition & 1 deletion dbms/src/Interpreters/ExpressionAnalyzer.cpp
Expand Up @@ -310,7 +310,7 @@ void ExpressionAnalyzer::makeSetsForIndexImpl(const ASTPtr & node, const Block &

if (!prepared_sets.count(arg->range)) /// Not already prepared.
{
if (typeid_cast<ASTSubquery *>(arg.get()) || typeid_cast<ASTIdentifier *>(arg.get()))
if (typeid_cast<ASTSubquery *>(arg.get()) || isIdentifier(arg))
{
if (settings.use_index_for_in_with_subqueries)
tryMakeSetForIndexFromSubquery(arg);
Expand Down
4 changes: 2 additions & 2 deletions dbms/src/Interpreters/GlobalSubqueriesVisitor.h
Expand Up @@ -55,7 +55,7 @@ class GlobalSubqueriesMatcher
ASTPtr table_name;
ASTPtr subquery_or_table_name;

if (typeid_cast<const ASTIdentifier *>(subquery_or_table_name_or_table_expression.get()))
if (isIdentifier(subquery_or_table_name_or_table_expression))
{
table_name = subquery_or_table_name_or_table_expression;
subquery_or_table_name = table_name;
Expand Down Expand Up @@ -86,7 +86,7 @@ class GlobalSubqueriesMatcher
if (table_name)
{
/// If this is already an external table, you do not need to add anything. Just remember its presence.
if (external_tables.end() != external_tables.find(static_cast<const ASTIdentifier &>(*table_name).name))
if (external_tables.end() != external_tables.find(*getIdentifierName(table_name)))
return;
}

Expand Down
20 changes: 14 additions & 6 deletions dbms/src/Interpreters/InterpreterSelectQuery.cpp
Expand Up @@ -147,14 +147,22 @@ InterpreterSelectQuery::InterpreterSelectQuery(

max_streams = settings.max_threads;

ASTPtr table_expression = getTableFunctionOrSubquery(query, 0);
ASTPtr table_expression = extractTableExpression(query, 0);

bool is_table_func = false;
bool is_subquery = false;
if (table_expression)
{
is_table_func = typeid_cast<const ASTFunction *>(table_expression.get());
is_subquery = typeid_cast<const ASTSelectWithUnionQuery *>(table_expression.get());
}

if (input)
{
/// Read from prepared input.
source_header = input->getHeader();
}
else if (table_expression && typeid_cast<const ASTSelectWithUnionQuery *>(table_expression.get()))
else if (is_subquery)
{
/// Read from subquery.
interpreter_subquery = std::make_unique<InterpreterSelectWithUnionQuery>(
Expand All @@ -164,7 +172,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(
}
else if (!storage)
{
if (table_expression && typeid_cast<const ASTFunction *>(table_expression.get()))
if (is_table_func)
{
/// Read from table function.
storage = context.getQueryContext().executeTableFunction(table_expression);
Expand Down Expand Up @@ -208,7 +216,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(
if (query_analyzer->isRewriteSubqueriesPredicate())
{
/// remake interpreter_subquery when PredicateOptimizer is rewrite subqueries and main table is subquery
if (table_expression && typeid_cast<ASTSelectWithUnionQuery *>(table_expression.get()))
if (is_subquery)
interpreter_subquery = std::make_unique<InterpreterSelectWithUnionQuery>(
table_expression, getSubqueryContext(context), required_columns, QueryProcessingStage::Complete, subquery_depth + 1,
only_analyze);
Expand Down Expand Up @@ -921,7 +929,7 @@ void InterpreterSelectQuery::executeFetchColumns(
/// If we need less number of columns that subquery have - update the interpreter.
if (required_columns.size() < source_header.columns())
{
ASTPtr subquery = getTableFunctionOrSubquery(query, 0);
ASTPtr subquery = extractTableExpression(query, 0);
if (!subquery)
throw Exception("Subquery expected", ErrorCodes::LOGICAL_ERROR);

Expand Down Expand Up @@ -1396,7 +1404,7 @@ bool hasWithTotalsInAnySubqueryInFromClause(const ASTSelectQuery & query)
* In other cases, totals will be computed on the initiating server of the query, and it is not necessary to read the data to the end.
*/

if (auto query_table = getTableFunctionOrSubquery(query, 0))
if (auto query_table = extractTableExpression(query, 0))
{
if (auto ast_union = typeid_cast<const ASTSelectWithUnionQuery *>(query_table.get()))
{
Expand Down
33 changes: 6 additions & 27 deletions dbms/src/Interpreters/TranslateQualifiedNamesVisitor.cpp
Expand Up @@ -89,38 +89,17 @@ std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(const ASTIdentifier

std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(const ASTQualifiedAsterisk & , const ASTPtr & ast, Data & data)
{
const std::vector<DatabaseAndTableWithAlias> & tables = data.tables;

if (ast->children.size() != 1)
throw Exception("Logical error: qualified asterisk must have exactly one child", ErrorCodes::LOGICAL_ERROR);

ASTIdentifier * ident = typeid_cast<ASTIdentifier *>(ast->children[0].get());
if (!ident)
throw Exception("Logical error: qualified asterisk must have identifier as its child", ErrorCodes::LOGICAL_ERROR);

size_t num_components = ident->children.size();
if (num_components > 2)
throw Exception("Qualified asterisk cannot have more than two qualifiers", ErrorCodes::UNKNOWN_ELEMENT_IN_AST);
auto & ident = ast->children[0];

DatabaseAndTableWithAlias db_and_table(*ident);
/// @note it could contain table alias as table name.
DatabaseAndTableWithAlias db_and_table(ident);

for (const auto & table_names : tables)
{
/// database.table.*, table.* or alias.*
if (num_components == 2)
{
if (!table_names.database.empty() &&
db_and_table.database == table_names.database &&
db_and_table.table == table_names.table)
return {};
}
else if (num_components == 0)
{
if ((!table_names.table.empty() && db_and_table.table == table_names.table) ||
(!table_names.alias.empty() && db_and_table.table == table_names.alias))
return {};
}
}
for (const auto & known_table : data.tables)
if (db_and_table.satisfies(known_table, true))
return {};

throw Exception("Unknown qualified identifier: " + ident->getAliasOrColumnName(), ErrorCodes::UNKNOWN_IDENTIFIER);
}
Expand Down
1 change: 1 addition & 0 deletions dbms/src/Interpreters/TranslateQualifiedNamesVisitor.h
Expand Up @@ -2,6 +2,7 @@

#include <vector>

#include <Core/Names.h>
#include <Interpreters/DatabaseAndTableWithAlias.h>
#include <Interpreters/InDepthNodeVisitor.h>

Expand Down
31 changes: 31 additions & 0 deletions dbms/src/Parsers/ASTIdentifier.cpp
Expand Up @@ -117,4 +117,35 @@ void setIdentifierSpecial(ASTPtr & ast)
id->setSpecial();
}

void addIdentifierQualifier(ASTIdentifier & identifier, const String & database, const String & table, const String & alias)
{
if (!alias.empty())
{
identifier.children.emplace_back(std::make_shared<ASTIdentifier>(alias));
}
else
{
if (!database.empty())
identifier.children.emplace_back(std::make_shared<ASTIdentifier>(database));
identifier.children.emplace_back(std::make_shared<ASTIdentifier>(table));
}
}

bool doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & database, const String & table)
{
size_t num_components = identifier.children.size();
if (num_components >= 3)
return *getIdentifierName(identifier.children[0]) == database &&
*getIdentifierName(identifier.children[1]) == table;
return false;
}

bool doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & table)
{
size_t num_components = identifier.children.size();
if (num_components >= 2)
return *getIdentifierName(identifier.children[0]) == table;
return false;
}

}
3 changes: 3 additions & 0 deletions dbms/src/Parsers/ASTIdentifier.h
Expand Up @@ -77,5 +77,8 @@ std::optional<String> getTableIdentifierName(const ASTIdentifier & node);
std::optional<String> getTableIdentifierName(const ASTPtr & ast);

void setIdentifierSpecial(ASTPtr & ast);
void addIdentifierQualifier(ASTIdentifier & identifier, const String & database, const String & table, const String & alias);
bool doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & table_or_alias);
bool doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & database, const String & table);

}