Fix inconsistent AST formatting when a keyword is used as type name

This commit is contained in:
Michael Kolupaev 2024-06-25 08:31:24 +00:00
parent bebed0598d
commit e4c84cf467
4 changed files with 23 additions and 1 deletions

View File

@ -213,6 +213,7 @@ bool IParserColumnDeclaration<NameParser>::parseImpl(Pos & pos, ASTPtr & node, E
return res;
};
/// Keep this list of keywords in sync with ParserDataType::parseImpl().
if (!null_check_without_moving()
&& !s_default.checkWithoutMoving(pos, expected)
&& !s_materialized.checkWithoutMoving(pos, expected)

View File

@ -1,5 +1,6 @@
#include <Parsers/ParserDataType.h>
#include <boost/algorithm/string/case_conv.hpp>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTIdentifier_fwd.h>
@ -103,12 +104,28 @@ bool ParserDataType::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
return false;
tryGetIdentifierNameInto(identifier, type_name);
/// Don't accept things like Array(`x.y`).
/// When parsing we accept quoted type names (e.g. `UInt64`), but when formatting we print them
/// unquoted (e.g. UInt64). This introduces problems when the string in the quotes is garbage:
/// * Array(`x.y`) -> Array(x.y) -> fails to parse
/// * `Null` -> Null -> parses as keyword instead of type name
/// Here we check for these cases and reject.
if (!std::all_of(type_name.begin(), type_name.end(), [](char c) { return isWordCharASCII(c) || c == '$'; }))
{
expected.add(pos, "type name");
return false;
}
/// Keywords that IParserColumnDeclaration recognizes before the type name.
/// E.g. reject CREATE TABLE a (x `Null`) because in "x Null" the Null would be parsed as
/// column attribute rather than type name.
{
String n = type_name;
boost::to_upper(n);
if (n == "NOT" || n == "NULL" || n == "DEFAULT" || n == "MATERIALIZED" || n == "EPHEMERAL" || n == "ALIAS" || n == "AUTO" || n == "PRIMARY" || n == "COMMENT" || n == "CODEC")
{
expected.add(pos, "type name");
return false;
}
}
String type_name_upper = Poco::toUpper(type_name);
String type_name_suffix;

View File

@ -0,0 +1,4 @@
create table a (x `Null`); -- { clientError SYNTAX_ERROR }
create table a (x f(`Null`)); -- { clientError SYNTAX_ERROR }
create table a (x Enum8(f(`Null`, 'World', 2))); -- { clientError SYNTAX_ERROR }
create table a (`value2` Enum8('Hello' = 1, equals(`Null`, 'World', 2), '!' = 3)); -- { clientError SYNTAX_ERROR }