2019-12-12 15:28:24 +00:00
|
|
|
#include <Interpreters/getTableExpressions.h>
|
2020-05-20 20:16:32 +00:00
|
|
|
#include <Interpreters/Context.h>
|
2019-12-12 15:28:24 +00:00
|
|
|
#include <Interpreters/InterpreterSelectWithUnionQuery.h>
|
|
|
|
#include <Parsers/ASTTablesInSelectQuery.h>
|
|
|
|
#include <Parsers/ASTSelectQuery.h>
|
|
|
|
#include <Storages/IStorage.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2019-12-12 16:54:04 +00:00
|
|
|
NameSet removeDuplicateColumns(NamesAndTypesList & columns)
|
|
|
|
{
|
|
|
|
NameSet names;
|
|
|
|
for (auto it = columns.begin(); it != columns.end();)
|
|
|
|
{
|
|
|
|
if (names.emplace(it->name).second)
|
|
|
|
++it;
|
|
|
|
else
|
|
|
|
columns.erase(it++);
|
|
|
|
}
|
|
|
|
return names;
|
|
|
|
}
|
|
|
|
|
2019-12-12 15:28:24 +00:00
|
|
|
std::vector<const ASTTableExpression *> getTableExpressions(const ASTSelectQuery & select_query)
|
|
|
|
{
|
|
|
|
if (!select_query.tables())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
std::vector<const ASTTableExpression *> tables_expression;
|
|
|
|
|
|
|
|
for (const auto & child : select_query.tables()->children)
|
|
|
|
{
|
|
|
|
const auto * tables_element = child->as<ASTTablesInSelectQueryElement>();
|
|
|
|
|
2019-12-15 06:34:43 +00:00
|
|
|
if (tables_element && tables_element->table_expression)
|
2019-12-12 15:28:24 +00:00
|
|
|
tables_expression.emplace_back(tables_element->table_expression->as<ASTTableExpression>());
|
|
|
|
}
|
|
|
|
|
|
|
|
return tables_expression;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ASTTableExpression * getTableExpression(const ASTSelectQuery & select, size_t table_number)
|
|
|
|
{
|
|
|
|
if (!select.tables())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
const auto & tables_in_select_query = select.tables()->as<ASTTablesInSelectQuery &>();
|
|
|
|
if (tables_in_select_query.children.size() <= table_number)
|
|
|
|
return {};
|
|
|
|
|
|
|
|
const auto & tables_element = tables_in_select_query.children[table_number]->as<ASTTablesInSelectQueryElement &>();
|
|
|
|
|
|
|
|
if (!tables_element.table_expression)
|
|
|
|
return {};
|
|
|
|
|
|
|
|
return tables_element.table_expression->as<ASTTableExpression>();
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTPtr extractTableExpression(const ASTSelectQuery & select, size_t table_number)
|
|
|
|
{
|
|
|
|
if (const ASTTableExpression * table_expression = getTableExpression(select, table_number))
|
|
|
|
{
|
|
|
|
if (table_expression->database_and_table_name)
|
|
|
|
return table_expression->database_and_table_name;
|
|
|
|
|
|
|
|
if (table_expression->table_function)
|
|
|
|
return table_expression->table_function;
|
|
|
|
|
|
|
|
if (table_expression->subquery)
|
|
|
|
return table_expression->subquery->children[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-12-13 18:46:55 +00:00
|
|
|
static NamesAndTypesList getColumnsFromTableExpression(const ASTTableExpression & table_expression, const Context & context,
|
|
|
|
NamesAndTypesList & materialized, NamesAndTypesList & aliases, NamesAndTypesList & virtuals)
|
2019-12-12 15:28:24 +00:00
|
|
|
{
|
|
|
|
NamesAndTypesList names_and_type_list;
|
|
|
|
if (table_expression.subquery)
|
|
|
|
{
|
|
|
|
const auto & subquery = table_expression.subquery->children.at(0);
|
|
|
|
names_and_type_list = InterpreterSelectWithUnionQuery::getSampleBlock(subquery, context).getNamesAndTypesList();
|
|
|
|
}
|
|
|
|
else if (table_expression.table_function)
|
|
|
|
{
|
|
|
|
const auto table_function = table_expression.table_function;
|
2020-04-22 06:22:14 +00:00
|
|
|
auto * query_context = const_cast<Context *>(&context.getQueryContext());
|
2019-12-12 15:28:24 +00:00
|
|
|
const auto & function_storage = query_context->executeTableFunction(table_function);
|
2020-04-22 06:01:33 +00:00
|
|
|
const auto & columns = function_storage->getColumns();
|
2019-12-13 18:46:55 +00:00
|
|
|
names_and_type_list = columns.getOrdinary();
|
|
|
|
materialized = columns.getMaterialized();
|
|
|
|
aliases = columns.getAliases();
|
2020-04-27 13:55:30 +00:00
|
|
|
virtuals = function_storage->getVirtuals();
|
2019-12-12 15:28:24 +00:00
|
|
|
}
|
|
|
|
else if (table_expression.database_and_table_name)
|
|
|
|
{
|
2020-03-13 10:30:55 +00:00
|
|
|
auto table_id = context.resolveStorageID(table_expression.database_and_table_name);
|
2020-03-06 20:38:19 +00:00
|
|
|
const auto & table = DatabaseCatalog::instance().getTable(table_id);
|
2020-04-22 06:01:33 +00:00
|
|
|
const auto & columns = table->getColumns();
|
2019-12-13 18:46:55 +00:00
|
|
|
names_and_type_list = columns.getOrdinary();
|
|
|
|
materialized = columns.getMaterialized();
|
|
|
|
aliases = columns.getAliases();
|
2020-04-27 13:55:30 +00:00
|
|
|
virtuals = table->getVirtuals();
|
2019-12-12 15:28:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return names_and_type_list;
|
|
|
|
}
|
|
|
|
|
2019-12-13 18:46:55 +00:00
|
|
|
NamesAndTypesList getColumnsFromTableExpression(const ASTTableExpression & table_expression, const Context & context)
|
|
|
|
{
|
|
|
|
NamesAndTypesList materialized;
|
|
|
|
NamesAndTypesList aliases;
|
|
|
|
NamesAndTypesList virtuals;
|
|
|
|
return getColumnsFromTableExpression(table_expression, context, materialized, aliases, virtuals);
|
|
|
|
}
|
|
|
|
|
2020-03-02 19:39:39 +00:00
|
|
|
std::vector<TableWithColumnNamesAndTypes> getDatabaseAndTablesWithColumns(const std::vector<const ASTTableExpression *> & table_expressions,
|
|
|
|
const Context & context)
|
2019-12-12 15:28:24 +00:00
|
|
|
{
|
2020-03-02 19:39:39 +00:00
|
|
|
std::vector<TableWithColumnNamesAndTypes> tables_with_columns;
|
2019-12-12 15:28:24 +00:00
|
|
|
|
2019-12-13 18:46:55 +00:00
|
|
|
if (!table_expressions.empty())
|
2019-12-12 15:28:24 +00:00
|
|
|
{
|
|
|
|
String current_database = context.getCurrentDatabase();
|
|
|
|
|
2019-12-13 18:46:55 +00:00
|
|
|
for (const ASTTableExpression * table_expression : table_expressions)
|
2019-12-12 15:28:24 +00:00
|
|
|
{
|
2019-12-13 18:46:55 +00:00
|
|
|
NamesAndTypesList materialized;
|
|
|
|
NamesAndTypesList aliases;
|
|
|
|
NamesAndTypesList virtuals;
|
|
|
|
NamesAndTypesList names_and_types = getColumnsFromTableExpression(*table_expression, context, materialized, aliases, virtuals);
|
|
|
|
|
2020-03-02 19:39:39 +00:00
|
|
|
removeDuplicateColumns(names_and_types);
|
|
|
|
|
|
|
|
tables_with_columns.emplace_back(
|
|
|
|
DatabaseAndTableWithAlias(*table_expression, current_database), names_and_types);
|
2019-12-12 15:28:24 +00:00
|
|
|
|
2019-12-13 18:46:55 +00:00
|
|
|
auto & table = tables_with_columns.back();
|
|
|
|
table.addHiddenColumns(materialized);
|
|
|
|
table.addHiddenColumns(aliases);
|
|
|
|
table.addHiddenColumns(virtuals);
|
2019-12-12 15:28:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tables_with_columns;
|
|
|
|
}
|
|
|
|
|
2020-03-02 19:39:39 +00:00
|
|
|
std::vector<TableWithColumnNames> getDatabaseAndTablesWithColumnNames(const std::vector<const ASTTableExpression *> & table_expressions,
|
|
|
|
const Context & context)
|
|
|
|
{
|
|
|
|
std::vector<TableWithColumnNamesAndTypes> tables_with_columns = getDatabaseAndTablesWithColumns(table_expressions, context);
|
|
|
|
std::vector<TableWithColumnNames> out;
|
|
|
|
out.reserve(tables_with_columns.size());
|
|
|
|
for (auto & table : tables_with_columns)
|
|
|
|
out.emplace_back(table.removeTypes());
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2019-12-12 15:28:24 +00:00
|
|
|
}
|