From e6adcfaad5a5007c862ca6e2fc402afdc0390c43 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Mon, 14 May 2018 18:47:38 +0300 Subject: [PATCH] Fixed element types for explicit set in IN function. [#CLICKHOUSE-3730] --- dbms/src/Functions/FunctionsMiscellaneous.cpp | 2 +- dbms/src/Interpreters/ExpressionAnalyzer.cpp | 48 +++++++++---------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/dbms/src/Functions/FunctionsMiscellaneous.cpp b/dbms/src/Functions/FunctionsMiscellaneous.cpp index d599e9bf1ec..ca35888a4b9 100644 --- a/dbms/src/Functions/FunctionsMiscellaneous.cpp +++ b/dbms/src/Functions/FunctionsMiscellaneous.cpp @@ -755,7 +755,7 @@ public: tuple = typeid_cast(materialized_tuple.get()); } - if (tuple) + if (tuple && type_tuple->getElements().size() != 1) { const Columns & tuple_columns = tuple->getColumns(); const DataTypes & tuple_types = type_tuple->getElements(); diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.cpp b/dbms/src/Interpreters/ExpressionAnalyzer.cpp index 5402684c640..b50780d339c 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.cpp +++ b/dbms/src/Interpreters/ExpressionAnalyzer.cpp @@ -1649,7 +1649,23 @@ void ExpressionAnalyzer::makeExplicitSet(const ASTFunction * node, const Block & const ASTPtr & left_arg = args.children.at(0); const ASTPtr & right_arg = args.children.at(1); + + auto getTupleTypeFromAst = [this](const ASTPtr & node) -> DataTypePtr + { + auto ast_function = typeid_cast(node.get()); + if (ast_function && ast_function->name == "tuple" && !ast_function->arguments->children.empty()) + { + /// Won't parse all values of outer tuple. + auto element = ast_function->arguments->children.at(0); + std::pair value_raw = evaluateConstantExpression(element, context); + return std::make_shared(DataTypes({value_raw.second})); + } + + return evaluateConstantExpression(node, context).second; + }; + const DataTypePtr & left_arg_type = sample_block.getByName(left_arg->getColumnName()).type; + const DataTypePtr & right_arg_type = getTupleTypeFromAst(right_arg); std::function getTupleDepth; getTupleDepth = [&getTupleDepth](const DataTypePtr & type) -> size_t @@ -1660,35 +1676,15 @@ void ExpressionAnalyzer::makeExplicitSet(const ASTFunction * node, const Block & return 0; }; - auto getTupleDepthFromAst = [&getTupleDepth](const ASTPtr & node) -> size_t - { - size_t depth = 0; - ASTPtr element = node; - - auto ast_function = typeid_cast(node.get()); - if (ast_function && ast_function->name == "tuple" && !ast_function->arguments->children.empty()) - { - ++depth; - element = ast_function->arguments->children.at(0); - } - - std::pair value_raw = evaluateConstantExpression(element, context); - return depth + getTupleDepth(value_raw.second); - }; - size_t left_tuple_depth = getTupleDepth(left_arg_type); - size_t right_tuple_depth = getTupleDepthFromAst(right_arg); + size_t right_tuple_depth = getTupleDepth(right_arg_type); - DataTypes set_element_types; - ASTPtr elements_ast = nullptr; - - if (left_tuple_depth > 0) - { - auto left_tuple_type = static_cast(left_arg_type.get()); + DataTypes set_element_types = {left_arg_type}; + auto left_tuple_type = typeid_cast(left_arg_type.get()); + if (left_tuple_type && left_tuple_type->getElements().size() != 1) set_element_types = left_tuple_type->getElements(); - } - else - set_element_types.push_back(left_arg_type); + + ASTPtr elements_ast = nullptr; /// 1 in 1; (1, 2) in (1, 2); identity(tuple(tuple(tuple(1)))) in tuple(tuple(tuple(1))); etc. if (left_tuple_depth == right_tuple_depth)