From d42a4323f6f95c3f810aa6fb965b19d3df561e86 Mon Sep 17 00:00:00 2001 From: Alexander Tokmakov Date: Sat, 25 May 2019 06:31:23 +0300 Subject: [PATCH] Fixes --- .../Formats/ConstantExpressionTemplate.cpp | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/dbms/src/Formats/ConstantExpressionTemplate.cpp b/dbms/src/Formats/ConstantExpressionTemplate.cpp index 29304d0b72e..a6b6f999681 100644 --- a/dbms/src/Formats/ConstantExpressionTemplate.cpp +++ b/dbms/src/Formats/ConstantExpressionTemplate.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -12,9 +13,9 @@ #include #include #include +#include #include #include -#include namespace DB @@ -25,6 +26,7 @@ namespace ErrorCodes extern const int CANNOT_CREATE_EXPRESSION_TEMPLATE; extern const int CANNOT_PARSE_EXPRESSION_USING_TEMPLATE; extern const int CANNOT_EVALUATE_EXPRESSION_TEMPLATE; + extern const int SYNTAX_ERROR; } class ReplaceLiteralsVisitor @@ -52,6 +54,8 @@ public: return; if (auto function = ast->as()) visit(*function); + else if (ast->as()) + throw DB::Exception("Identifier in constant expression", ErrorCodes::SYNTAX_ERROR); else visitChildren(ast, {}); } @@ -85,7 +89,6 @@ private: return false; if (literal->begin && literal->end) { - // TODO ensure column_name is unique (there was no _dummy_x identifier in expression) String column_name = "_dummy_" + std::to_string(replaced_literals.size()); replaced_literals.emplace_back(literal, column_name); ast = std::make_shared(column_name); @@ -137,7 +140,7 @@ ConstantExpressionTemplate::ConstantExpressionTemplate(const IDataType & result_ type = std::make_shared(); else if (type_info.isNativeUInt()) type = std::make_shared(); - else + else if (!type_info.isFloat()) need_special_parser[i] = false; /// Allow literal to be NULL, if result column has nullable type @@ -172,7 +175,8 @@ void ConstantExpressionTemplate::parseExpression(ReadBuffer & istr, const Format size_t cur_column = 0; try { - ParserNumber parser; + ParserKeyword parser_null("NULL"); + ParserNumber parser_number; size_t cur_token = 0; while (cur_column < literals.columns()) { @@ -188,22 +192,27 @@ void ConstantExpressionTemplate::parseExpression(ReadBuffer & istr, const Format const IDataType & type = *literals.getByPosition(cur_column).type; if (need_special_parser[cur_column]) { + WhichDataType type_info(type); + bool nullable = type_info.isNullable(); + if (nullable) + type_info = WhichDataType(dynamic_cast(type).getNestedType()); + Tokens tokens_number(istr.position(), istr.buffer().end()); TokenIterator iterator(tokens_number); Expected expected; ASTPtr ast; - if (!parser.parse(iterator, ast, expected)) + if (nullable && parser_null.parse(iterator, ast, expected)) + ast = std::make_shared(Field()); + else if (!parser_number.parse(iterator, ast, expected)) throw DB::Exception("Cannot parse literal", ErrorCodes::CANNOT_PARSE_EXPRESSION_USING_TEMPLATE); istr.position() = const_cast(iterator->begin); - Field number = ast->as().value; + Field & number = ast->as().value; - WhichDataType type_info(type); - if (type_info.isNullable()) - type_info = WhichDataType(dynamic_cast(type).getNestedType()); // TODO also check type of Array(T), if T is arithmetic if ((number.getType() == Field::Types::UInt64 && type_info.isUInt64()) || (number.getType() == Field::Types::Int64 && type_info.isInt64()) - || (number.getType() == Field::Types::Float64 && type_info.isFloat64())) + || (number.getType() == Field::Types::Float64 && type_info.isFloat64()) + || nullable) { columns[cur_column]->insert(number); }