global join: fix wrong name qualification (save replaced table name as alias)

This commit is contained in:
chertus 2019-04-10 20:41:19 +03:00
parent f40ab95739
commit ee6c83a2f7
3 changed files with 94 additions and 27 deletions

View File

@ -46,48 +46,36 @@ public:
has_global_subqueries(has_global_subqueries_)
{}
void addExternalStorage(ASTPtr & subquery_or_table_name_or_table_expression)
void addExternalStorage(ASTPtr & ast, bool set_alias = false)
{
/// With nondistributed queries, creating temporary tables does not make sense.
if (!is_remote)
return;
ASTPtr subquery;
ASTPtr table_name;
ASTPtr subquery_or_table_name;
bool is_table = false;
ASTPtr subquery_or_table_name = ast; /// ASTIdentifier | ASTSubquery | ASTTableExpression
if (subquery_or_table_name_or_table_expression->as<ASTIdentifier>())
{
table_name = subquery_or_table_name_or_table_expression;
subquery_or_table_name = table_name;
}
else if (const auto * ast_table_expr = subquery_or_table_name_or_table_expression->as<ASTTableExpression>())
if (const auto * ast_table_expr = ast->as<ASTTableExpression>())
{
subquery_or_table_name = ast_table_expr->subquery;
if (ast_table_expr->database_and_table_name)
{
table_name = ast_table_expr->database_and_table_name;
subquery_or_table_name = table_name;
}
else if (ast_table_expr->subquery)
{
subquery = ast_table_expr->subquery;
subquery_or_table_name = subquery;
subquery_or_table_name = ast_table_expr->database_and_table_name;
is_table = true;
}
}
else if (subquery_or_table_name_or_table_expression->as<ASTSubquery>())
{
subquery = subquery_or_table_name_or_table_expression;
subquery_or_table_name = subquery;
}
else if (ast->as<ASTIdentifier>())
is_table = true;
if (!subquery_or_table_name)
throw Exception("Logical error: unknown AST element passed to ExpressionAnalyzer::addExternalStorage method",
ErrorCodes::LOGICAL_ERROR);
if (table_name)
if (is_table)
{
/// 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(*getIdentifierName(table_name)))
if (external_tables.end() != external_tables.find(*getIdentifierName(subquery_or_table_name)))
return;
}
@ -114,8 +102,16 @@ public:
*/
auto database_and_table_name = createTableIdentifier("", external_table_name);
if (set_alias)
{
String alias = subquery_or_table_name->tryGetAlias();
if (auto * table_name = subquery_or_table_name->as<ASTIdentifier>())
if (alias.empty())
alias = table_name->shortName();
database_and_table_name->setAlias(alias);
}
if (auto * ast_table_expr = subquery_or_table_name_or_table_expression->as<ASTTableExpression>())
if (auto * ast_table_expr = ast->as<ASTTableExpression>())
{
ast_table_expr->subquery.reset();
ast_table_expr->database_and_table_name = database_and_table_name;
@ -124,7 +120,7 @@ public:
ast_table_expr->children.emplace_back(database_and_table_name);
}
else
subquery_or_table_name_or_table_expression = database_and_table_name;
ast = database_and_table_name;
external_tables[external_table_name] = external_storage;
subqueries_for_sets[external_table_name].source = interpreter->execute().in;
@ -170,7 +166,7 @@ private:
{
if (table_elem.table_join && table_elem.table_join->as<ASTTableJoin &>().locality == ASTTableJoin::Locality::Global)
{
data.addExternalStorage(table_elem.table_expression);
data.addExternalStorage(table_elem.table_expression, true);
data.has_global_subqueries = true;
}
}

View File

@ -0,0 +1,12 @@
One Hundred
Two Hundred
One Hundred
Two Hundred
One Hundred
Two Hundred
One Hundred
Two Hundred
One Hundred
Two Hundred
One Hundred
Two Hundred

View File

@ -0,0 +1,59 @@
USE test;
DROP TABLE IF EXISTS local_table;
DROP TABLE IF EXISTS other_table;
CREATE TABLE local_table
(
id Int32,
name String,
ts DateTime,
oth_id Int32
) ENGINE = MergeTree() PARTITION BY toMonday(ts) ORDER BY (ts, id);
CREATE TABLE other_table
(
id Int32,
name String,
ts DateTime,
trd_id Int32
) ENGINE = MergeTree() PARTITION BY toMonday(ts) ORDER BY (ts, id);
INSERT INTO local_table VALUES(1, 'One', now(), 100);
INSERT INTO local_table VALUES(2, 'Two', now(), 200);
INSERT INTO other_table VALUES(100, 'One Hundred', now(), 1000);
INSERT INTO other_table VALUES(200, 'Two Hundred', now(), 2000);
-- FIXME: test.other_table -> other_table in first query breaks test (external tables cache error)
select t2.name from remote('127.0.0.2', 'test.local_table') as t1
left join test.other_table as t2
on t1.oth_id = t2.id
order by t2.name;
select t2.name from test.other_table as t2
global right join remote('127.0.0.2', 'test.local_table') as t1
on t1.oth_id = t2.id
order by t2.name;
select t2.name from remote('127.0.0.2', 'test.local_table') as t1
global left join other_table as t2
on t1.oth_id = t2.id
order by t2.name;
select t2.name from remote('127.0.0.2', 'test.local_table') as t1
global left join other_table as t2
on t1.oth_id = t2.id
order by t2.name;
select other_table.name from remote('127.0.0.2', 'test.local_table') as t1
global left join other_table
on t1.oth_id = other_table.id
order by other_table.name;
select other_table.name from remote('127.0.0.2', 'test.local_table') as t1
global left join other_table as t2
on t1.oth_id = other_table.id
order by other_table.name;
DROP TABLE local_table;
DROP TABLE other_table;