From 7731ea7905be089c943a82af6ff7cb16a5966bc6 Mon Sep 17 00:00:00 2001 From: vdimir Date: Tue, 25 Apr 2023 11:28:54 +0000 Subject: [PATCH] Fix key not found error for queries with multiple StorageJoin --- src/Interpreters/TableJoin.cpp | 9 ++++++++ src/Interpreters/TableJoin.h | 8 +++++++ src/Storages/StorageJoin.cpp | 5 +++-- .../02724_mutliple_storage_join.reference | 6 ++++++ .../02724_mutliple_storage_join.sql | 21 +++++++++++++++++++ 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/queries/0_stateless/02724_mutliple_storage_join.reference create mode 100644 tests/queries/0_stateless/02724_mutliple_storage_join.sql diff --git a/src/Interpreters/TableJoin.cpp b/src/Interpreters/TableJoin.cpp index 7ea7a2652635..2d882083f3d8 100644 --- a/src/Interpreters/TableJoin.cpp +++ b/src/Interpreters/TableJoin.cpp @@ -147,6 +147,7 @@ void TableJoin::addDisjunct() void TableJoin::addOnKeys(ASTPtr & left_table_ast, ASTPtr & right_table_ast) { addKey(left_table_ast->getColumnName(), right_table_ast->getAliasOrColumnName(), left_table_ast, right_table_ast); + right_key_aliases[right_table_ast->getColumnName()] = right_table_ast->getAliasOrColumnName(); } /// @return how many times right key appears in ON section. @@ -662,6 +663,14 @@ String TableJoin::renamedRightColumnName(const String & name) const return name; } +String TableJoin::renamedRightColumnNameWithAlias(const String & name) const +{ + auto renamed = renamedRightColumnName(name); + if (const auto it = right_key_aliases.find(renamed); it != right_key_aliases.end()) + return it->second; + return renamed; +} + void TableJoin::setRename(const String & from, const String & to) { renames[from] = to; diff --git a/src/Interpreters/TableJoin.h b/src/Interpreters/TableJoin.h index 99b683b77134..0e0c905e30c6 100644 --- a/src/Interpreters/TableJoin.h +++ b/src/Interpreters/TableJoin.h @@ -156,6 +156,13 @@ class TableJoin /// Original name -> name. Only renamed columns. std::unordered_map renames; + /// Map column name to actual key name that can be an alias. + /// Example: SELECT r.id as rid from t JOIN r ON t.id = rid + /// Map: r.id -> rid + /// Required only for StorageJoin to map join keys back to original column names. + /// (workaround for ExpressionAnalyzer) + std::unordered_map right_key_aliases; + VolumePtr tmp_volume; std::shared_ptr right_storage_join; @@ -333,6 +340,7 @@ class TableJoin Block getRequiredRightKeys(const Block & right_table_keys, std::vector & keys_sources) const; String renamedRightColumnName(const String & name) const; + String renamedRightColumnNameWithAlias(const String & name) const; void setRename(const String & from, const String & to); void resetKeys(); diff --git a/src/Storages/StorageJoin.cpp b/src/Storages/StorageJoin.cpp index dec741beb450..23bcdd23484f 100644 --- a/src/Storages/StorageJoin.cpp +++ b/src/Storages/StorageJoin.cpp @@ -220,12 +220,13 @@ HashJoinPtr StorageJoin::getJoinLocked(std::shared_ptr analyzed_join, Names left_key_names_resorted; for (const auto & key_name : key_names) { - const auto & renamed_key = analyzed_join->renamedRightColumnName(key_name); + const auto & renamed_key = analyzed_join->renamedRightColumnNameWithAlias(key_name); /// find position of renamed_key in key_names_right auto it = std::find(key_names_right.begin(), key_names_right.end(), renamed_key); if (it == key_names_right.end()) throw Exception(ErrorCodes::INCOMPATIBLE_TYPE_OF_JOIN, - "Key '{}' not found in JOIN ON section. All Join engine keys '{}' have to be used", key_name, fmt::join(key_names, ", ")); + "Key '{}' not found in JOIN ON section. Join engine key{} '{}' have to be used", + key_name, key_names.size() > 1 ? "s" : "", fmt::join(key_names, ", ")); const size_t key_position = std::distance(key_names_right.begin(), it); left_key_names_resorted.push_back(key_names_left[key_position]); } diff --git a/tests/queries/0_stateless/02724_mutliple_storage_join.reference b/tests/queries/0_stateless/02724_mutliple_storage_join.reference new file mode 100644 index 000000000000..f7eb44d66e0b --- /dev/null +++ b/tests/queries/0_stateless/02724_mutliple_storage_join.reference @@ -0,0 +1,6 @@ +0 +0 +0 +0 +0 +0 diff --git a/tests/queries/0_stateless/02724_mutliple_storage_join.sql b/tests/queries/0_stateless/02724_mutliple_storage_join.sql new file mode 100644 index 000000000000..286e867704df --- /dev/null +++ b/tests/queries/0_stateless/02724_mutliple_storage_join.sql @@ -0,0 +1,21 @@ +CREATE TABLE user(id UInt32, name String) ENGINE = Join(ANY, LEFT, id); +INSERT INTO user VALUES (1,'U1')(2,'U2')(3,'U3'); + +CREATE TABLE product(id UInt32, name String, cate String) ENGINE = Join(ANY, LEFT, id); +INSERT INTO product VALUES (1,'P1','C1')(2,'P2','C1')(3,'P3','C2'); + +CREATE TABLE order(id UInt32, pId UInt32, uId UInt32) ENGINE = TinyLog; +INSERT INTO order VALUES (1,1,1)(2,1,2)(3,2,3); + +SELECT ignore(*) FROM ( + SELECT + uId, + user.id as `uuu` + FROM order + LEFT ANY JOIN user + ON uId = `uuu` +); + +SELECT ignore(*) FROM order +LEFT ANY JOIN user ON uId = user.id +LEFT ANY JOIN product ON pId = product.id;