ClickHouse/src/Parsers/ParserDataType.cpp
Alexey Milovidov c27f90c8ed
Update src/Parsers/ParserDataType.cpp
Co-authored-by: Nikolay Degterinsky <43110995+evillique@users.noreply.github.com>
2022-12-27 17:16:31 +03:00

148 lines
4.7 KiB
C++

#include <Parsers/ParserDataType.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTIdentifier_fwd.h>
#include <Parsers/CommonParsers.h>
#include <Parsers/ExpressionElementParsers.h>
#include <Parsers/ParserCreateQuery.h>
namespace DB
{
namespace
{
/// Wrapper to allow mixed lists of nested and normal types.
/// Parameters are either:
/// - Nested table elements;
/// - Enum element in form of 'a' = 1;
/// - literal;
/// - another data type (or identifier)
class ParserDataTypeArgument : public IParserBase
{
private:
const char * getName() const override { return "data type argument"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
ParserNestedTable nested_parser;
ParserDataType data_type_parser;
ParserAllCollectionsOfLiterals literal_parser(false);
const char * operators[] = {"=", "equals", nullptr};
ParserLeftAssociativeBinaryOperatorList enum_parser(operators, std::make_unique<ParserLiteral>());
if (pos->type == TokenType::BareWord && std::string_view(pos->begin, pos->size()) == "Nested")
return nested_parser.parse(pos, node, expected);
return enum_parser.parse(pos, node, expected)
|| literal_parser.parse(pos, node, expected)
|| data_type_parser.parse(pos, node, expected);
}
};
}
bool ParserDataType::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ParserNestedTable nested;
if (nested.parse(pos, node, expected))
return true;
String type_name;
ParserIdentifier name_parser;
ASTPtr identifier;
if (!name_parser.parse(pos, identifier, expected))
return false;
tryGetIdentifierNameInto(identifier, type_name);
String type_name_upper = Poco::toUpper(type_name);
String type_name_suffix;
/// Special cases for compatibility with SQL standard. We can parse several words as type name
/// only for certain first words, otherwise we don't know how many words to parse
if (type_name_upper == "NATIONAL")
{
if (ParserKeyword("CHARACTER LARGE OBJECT").ignore(pos))
type_name_suffix = "CHARACTER LARGE OBJECT";
else if (ParserKeyword("CHARACTER VARYING").ignore(pos))
type_name_suffix = "CHARACTER VARYING";
else if (ParserKeyword("CHAR VARYING").ignore(pos))
type_name_suffix = "CHAR VARYING";
else if (ParserKeyword("CHARACTER").ignore(pos))
type_name_suffix = "CHARACTER";
else if (ParserKeyword("CHAR").ignore(pos))
type_name_suffix = "CHAR";
}
else if (type_name_upper == "BINARY" ||
type_name_upper == "CHARACTER" ||
type_name_upper == "CHAR" ||
type_name_upper == "NCHAR")
{
if (ParserKeyword("LARGE OBJECT").ignore(pos))
type_name_suffix = "LARGE OBJECT";
else if (ParserKeyword("VARYING").ignore(pos))
type_name_suffix = "VARYING";
}
else if (type_name_upper == "DOUBLE")
{
if (ParserKeyword("PRECISION").ignore(pos))
type_name_suffix = "PRECISION";
}
else if (type_name_upper.find("INT") != std::string::npos)
{
/// Support SIGNED and UNSIGNED integer type modifiers for compatibility with MySQL
if (ParserKeyword("SIGNED").ignore(pos))
type_name_suffix = "SIGNED";
else if (ParserKeyword("UNSIGNED").ignore(pos))
type_name_suffix = "UNSIGNED";
else if (pos->type == TokenType::OpeningRoundBracket)
{
++pos;
if (pos->type == TokenType::Number)
++pos;
if (pos->type != TokenType::ClosingRoundBracket)
return false;
++pos;
if (ParserKeyword("SIGNED").ignore(pos))
type_name_suffix = "SIGNED";
else if (ParserKeyword("UNSIGNED").ignore(pos))
type_name_suffix = "UNSIGNED";
}
}
if (!type_name_suffix.empty())
type_name = type_name_upper + " " + type_name_suffix;
auto function_node = std::make_shared<ASTFunction>();
function_node->name = type_name;
function_node->no_empty_args = true;
if (pos->type != TokenType::OpeningRoundBracket)
{
node = function_node;
return true;
}
++pos;
/// Parse optional parameters
ParserList args_parser(std::make_unique<ParserDataTypeArgument>(), std::make_unique<ParserToken>(TokenType::Comma));
ASTPtr expr_list_args;
if (!args_parser.parse(pos, expr_list_args, expected))
return false;
if (pos->type != TokenType::ClosingRoundBracket)
return false;
++pos;
function_node->arguments = expr_list_args;
function_node->children.push_back(function_node->arguments);
node = function_node;
return true;
}
}