This commit is contained in:
vdimir 2022-12-08 10:05:26 +00:00
parent 36562fdbbb
commit 1d9096c9ac
No known key found for this signature in database
GPG Key ID: 6EE4CE2BEDC51862
5 changed files with 31 additions and 20 deletions

View File

@ -19,6 +19,11 @@ namespace ErrorCodes
namespace
{
bool isDeterminedIdentifier(JoinIdentifierPos pos)
{
return pos == JoinIdentifierPos::Left || pos == JoinIdentifierPos::Right;
}
bool isLeftIdentifier(JoinIdentifierPos pos)
{
/// Unknown identifiers considered as left, we will try to process it on later stages
@ -79,7 +84,7 @@ void CollectJoinOnKeysMatcher::Data::asofToJoinKeys()
void CollectJoinOnKeysMatcher::visit(const ASTIdentifier & ident, const ASTPtr & ast, CollectJoinOnKeysMatcher::Data & data)
{
if (auto expr_from_table = getTableForIdentifiers(ast, false, data); expr_from_table != JoinIdentifierPos::Unknown)
if (auto expr_from_table = getTableForIdentifiers(ast, false, data); isDeterminedIdentifier(expr_from_table))
data.analyzed_join.addJoinCondition(ast, isLeftIdentifier(expr_from_table));
else
throw Exception("Unexpected identifier '" + ident.name() + "' in JOIN ON section",
@ -105,27 +110,26 @@ void CollectJoinOnKeysMatcher::visit(const ASTFunction & func, const ASTPtr & as
ASTPtr left = func.arguments->children.at(0);
ASTPtr right = func.arguments->children.at(1);
auto table_numbers = getTableNumbers(left, right, data);
if (table_numbers.first == table_numbers.second)
{
if (table_numbers.first == JoinIdentifierPos::Unknown)
throw Exception("Ambiguous column in expression '" + queryToString(ast) + "' in JOIN ON section",
ErrorCodes::AMBIGUOUS_COLUMN_NAME);
if (!isDeterminedIdentifier(table_numbers.first))
throw Exception(ErrorCodes::AMBIGUOUS_COLUMN_NAME,
"Ambiguous columns in expression '{}' in JOIN ON section", queryToString(ast));
data.analyzed_join.addJoinCondition(ast, isLeftIdentifier(table_numbers.first));
return;
}
if ((table_numbers.first == JoinIdentifierPos::Left && table_numbers.second == JoinIdentifierPos::Right) ||
(table_numbers.first == JoinIdentifierPos::Right && table_numbers.second == JoinIdentifierPos::Left))
if ((isLeftIdentifier(table_numbers.first) && isRightIdentifier(table_numbers.second)) ||
(isRightIdentifier(table_numbers.first) && isLeftIdentifier(table_numbers.second)))
{
data.addJoinKeys(left, right, table_numbers);
return;
}
throw Exception(ErrorCodes::AMBIGUOUS_COLUMN_NAME,
"Cannot detect left and right JOIN keys. JOIN ON section is ambiguous for expression '{}'", queryToString(ast));
}
if (auto expr_from_table = getTableForIdentifiers(ast, false, data); expr_from_table != JoinIdentifierPos::Unknown)
if (auto expr_from_table = getTableForIdentifiers(ast, false, data); isDeterminedIdentifier(expr_from_table))
{
data.analyzed_join.addJoinCondition(ast, isLeftIdentifier(expr_from_table));
return;
@ -208,7 +212,7 @@ JoinIdentifierPos CollectJoinOnKeysMatcher::getTableForIdentifiers(const ASTPtr
std::vector<const ASTIdentifier *> identifiers;
getIdentifiers(ast, identifiers);
if (identifiers.empty())
return JoinIdentifierPos::Unknown;
return JoinIdentifierPos::Constant;
JoinIdentifierPos table_number = JoinIdentifierPos::Unknown;

View File

@ -32,6 +32,8 @@ enum class JoinIdentifierPos
Left,
/// Right side of JOIN
Right,
/// Identifier is not a column, but for example a constant
Constant,
};
using JoinIdentifierPosPair = std::pair<JoinIdentifierPos, JoinIdentifierPos>;

View File

@ -62,7 +62,6 @@ namespace ErrorCodes
extern const int EMPTY_LIST_OF_COLUMNS_QUERIED;
extern const int EMPTY_NESTED_TABLE;
extern const int EXPECTED_ALL_OR_ANY;
extern const int INCOMPATIBLE_TYPE_OF_JOIN;
extern const int INVALID_JOIN_ON_EXPRESSION;
extern const int LOGICAL_ERROR;
extern const int NOT_IMPLEMENTED;
@ -792,8 +791,8 @@ void collectJoinedColumns(TableJoin & analyzed_join, ASTTableJoin & table_join,
if (any_keys_empty)
throw DB::Exception(ErrorCodes::INVALID_JOIN_ON_EXPRESSION,
"Cannot get JOIN keys from JOIN ON section: '{}'",
queryToString(table_join.on_expression));
"Cannot get JOIN keys from JOIN ON section: '{}', found keys: {}",
queryToString(table_join.on_expression), TableJoin::formatClauses(analyzed_join.getClauses()));
if (is_asof)
{

View File

@ -43,7 +43,7 @@ JOIN system.one AS y USING dummy;
SELECT * FROM ( SELECT [toUInt32(dummy), toUInt32(dummy)] AS dummy FROM system.one ) AS x ARRAY JOIN dummy
JOIN (select toInt32(dummy) as dummy from system.one ) AS y USING dummy;
SELECT dummy > 0, toTypeName(any(dummy)), any(toTypeName(dummy))
SELECT dummy > 0, toTypeName(any(dummy)), any(toTypeName(dummy))
FROM ( SELECT [toUInt32(dummy), toUInt32(dummy)] AS dummy FROM system.one ) AS x ARRAY JOIN dummy
JOIN ( SELECT toInt32(dummy) AS dummy FROM system.one ) AS y USING dummy GROUP BY (dummy > 0);

View File

@ -33,11 +33,10 @@ SELECT * FROM (SELECT key3 AS c, key1 AS a, key2 AS b FROM t1) AS t1 ALL INNER J
SELECT * FROM (SELECT key3 AS c, key1 AS a, key2 AS b FROM t1) AS t1 ALL INNER JOIN tj ON t1.a = tj.key1 AND t1.b = tj.key2 AND t1.c = tj.key3 ORDER BY t1.a;
SELECT * FROM (SELECT key3 AS c, key1 AS a, key2 AS b FROM t1) AS t1 ALL INNER JOIN tj ON t1.c = tj.key3 AND t1.a = tj.key1 AND t1.b = tj.key2 ORDER BY t1.a;
-- TODO (vdimir): uncomment after https://github.com/ClickHouse/ClickHouse/pull/44016
-- SELECT * FROM t1 ALL INNER JOIN tj ON t1.key1 = tj.key1 AND t1.key3 = tj.key3 AND t1.key2 = tj.key2 AND 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
-- SELECT * FROM t1 ALL INNER JOIN tj ON t1.key1 = tj.key1 AND t1.key3 = tj.key3 AND t1.key2 = tj.key2 AND 0; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
-- SELECT * FROM t1 ALL INNER JOIN tj ON t1.key1 = tj.key1 AND t1.key3 = tj.key3 AND t1.key2 = tj.key2 AND 1 == 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
-- SELECT * FROM t1 ALL INNER JOIN tj ON t1.key1 = tj.key1 AND t1.key3 = tj.key3 AND t1.key2 = tj.key2 AND 1 > 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
SELECT * FROM t1 ALL INNER JOIN tj ON t1.key1 = tj.key1 AND t1.key3 = tj.key3 AND t1.key2 = tj.key2 AND 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
SELECT * FROM t1 ALL INNER JOIN tj ON t1.key1 = tj.key1 AND t1.key3 = tj.key3 AND t1.key2 = tj.key2 AND 0; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
SELECT * FROM t1 ALL INNER JOIN tj ON t1.key1 = tj.key1 AND t1.key3 = tj.key3 AND t1.key2 = tj.key2 AND 1 == 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
SELECT * FROM t1 ALL INNER JOIN tj ON t1.key1 = tj.key1 AND t1.key3 = tj.key3 AND t1.key2 = tj.key2 AND 1 > 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
SELECT '--- incompatible ---';
SELECT * FROM t1 ALL INNER JOIN tj ON 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
@ -46,6 +45,13 @@ SELECT * FROM t1 ALL INNER JOIN tj ON NULL; -- { serverError INCOMPATIBLE_TYPE_O
SELECT * FROM t1 ALL INNER JOIN tj ON 1 == 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
SELECT * FROM t1 ALL INNER JOIN tj ON 1 != 1; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
-- Here is another error code because equality is handled differently in CollectJoinOnKeysVisitor.
-- We can change the error code, but it will become inconsistent for other cases
-- where we actually expect AMBIGUOUS_COLUMN_NAME instead of INVALID_JOIN_ON_EXPRESSION.
-- These checks will be more reliable after switching to a new analyzer.
SELECT * FROM t1 ALL INNER JOIN tj ON 1 == 1; -- { serverError AMBIGUOUS_COLUMN_NAME }
SELECT * FROM t1 ALL INNER JOIN tj ON 1 == 2; -- { serverError AMBIGUOUS_COLUMN_NAME }
SELECT * FROM t1 ALL INNER JOIN tj USING (key2, key3); -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
SELECT * FROM t1 ALL INNER JOIN tj USING (key1, key2, attr) SETTINGS allow_experimental_analyzer = 0; -- { serverError INCOMPATIBLE_TYPE_OF_JOIN }
SELECT * FROM t1 ALL INNER JOIN tj USING (key1, key2, attr) SETTINGS allow_experimental_analyzer = 1; -- { serverError UNKNOWN_IDENTIFIER }