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_) 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. /// With nondistributed queries, creating temporary tables does not make sense.
if (!is_remote) if (!is_remote)
return; return;
ASTPtr subquery; bool is_table = false;
ASTPtr table_name; ASTPtr subquery_or_table_name = ast; /// ASTIdentifier | ASTSubquery | ASTTableExpression
ASTPtr subquery_or_table_name;
if (subquery_or_table_name_or_table_expression->as<ASTIdentifier>()) if (const auto * ast_table_expr = ast->as<ASTTableExpression>())
{
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>())
{ {
subquery_or_table_name = ast_table_expr->subquery;
if (ast_table_expr->database_and_table_name) if (ast_table_expr->database_and_table_name)
{ {
table_name = ast_table_expr->database_and_table_name; subquery_or_table_name = ast_table_expr->database_and_table_name;
subquery_or_table_name = table_name; is_table = true;
}
else if (ast_table_expr->subquery)
{
subquery = ast_table_expr->subquery;
subquery_or_table_name = subquery;
} }
} }
else if (subquery_or_table_name_or_table_expression->as<ASTSubquery>()) else if (ast->as<ASTIdentifier>())
{ is_table = true;
subquery = subquery_or_table_name_or_table_expression;
subquery_or_table_name = subquery;
}
if (!subquery_or_table_name) if (!subquery_or_table_name)
throw Exception("Logical error: unknown AST element passed to ExpressionAnalyzer::addExternalStorage method", throw Exception("Logical error: unknown AST element passed to ExpressionAnalyzer::addExternalStorage method",
ErrorCodes::LOGICAL_ERROR); 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 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; return;
} }
@ -114,8 +102,16 @@ public:
*/ */
auto database_and_table_name = createTableIdentifier("", external_table_name); 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->subquery.reset();
ast_table_expr->database_and_table_name = database_and_table_name; 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); ast_table_expr->children.emplace_back(database_and_table_name);
} }
else else
subquery_or_table_name_or_table_expression = database_and_table_name; ast = database_and_table_name;
external_tables[external_table_name] = external_storage; external_tables[external_table_name] = external_storage;
subqueries_for_sets[external_table_name].source = interpreter->execute().in; 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) 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; 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;