mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 01:51:59 +00:00
Fix inconsistent formatting for tupleElement (for fuzzer)
fuzzer sometimes [1] may inserts tupleElement() created from ASTLiteral: Function_tupleElement, 0xx -ExpressionList_, 0xx --Literal_Int64_255, 0xx --Literal_Int64_100, 0xx And in this case it will be printed as "255.100", which later will be parsed as float, and formatting will be inconsistent. So instead of printing it as regular tuple, let's print it as ExpressionList instead (i.e. with ", " delimiter). Simple reproducer: void ast() { auto arg1 = std::make_shared<ASTLiteral>(Field(255)); auto arg2 = std::make_shared<ASTLiteral>(Field(100)); auto func = makeASTFunction("tupleElement", arg1, arg2); auto ast = func; std::cerr << ast->formatForErrorMessage() << std::endl; std::cerr << ast->dumpTree() << std::endl; } [1]: https://clickhouse-test-reports.s3.yandex.net/23517/f1187aeb69109c88f0be978b8083080c7a843820/fuzzer_debug/report.html#fail1
This commit is contained in:
parent
d6854e80f7
commit
a5a8ecfe42
@ -383,14 +383,40 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format
|
||||
|
||||
if (!written && 0 == strcmp(name.c_str(), "tupleElement"))
|
||||
{
|
||||
// fuzzer sometimes may inserts tupleElement() created from ASTLiteral:
|
||||
//
|
||||
// Function_tupleElement, 0xx
|
||||
// -ExpressionList_, 0xx
|
||||
// --Literal_Int64_255, 0xx
|
||||
// --Literal_Int64_100, 0xx
|
||||
//
|
||||
// And in this case it will be printed as "255.100", which
|
||||
// later will be parsed as float, and formatting will be
|
||||
// inconsistent.
|
||||
//
|
||||
// So instead of printing it as regular tuple,
|
||||
// let's print it as ExpressionList instead (i.e. with ", " delimiter).
|
||||
bool tuple_arguments_valid = true;
|
||||
const auto * lit_left = arguments->children[0]->as<ASTLiteral>();
|
||||
const auto * lit_right = arguments->children[1]->as<ASTLiteral>();
|
||||
|
||||
if (lit_left)
|
||||
{
|
||||
Field::Types::Which type = lit_left->value.getType();
|
||||
if (type != Field::Types::Tuple && type != Field::Types::Array)
|
||||
{
|
||||
tuple_arguments_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
// It can be printed in a form of 'x.1' only if right hand side
|
||||
// is an unsigned integer lineral. We also allow nonnegative
|
||||
// signed integer literals, because the fuzzer sometimes inserts
|
||||
// them, and we want to have consistent formatting.
|
||||
if (const auto * lit = arguments->children[1]->as<ASTLiteral>())
|
||||
if (tuple_arguments_valid && lit_right)
|
||||
{
|
||||
if (isInt64FieldType(lit->value.getType())
|
||||
&& lit->value.get<Int64>() >= 0)
|
||||
if (isInt64FieldType(lit_right->value.getType())
|
||||
&& lit_right->value.get<Int64>() >= 0)
|
||||
{
|
||||
if (frame.need_parens)
|
||||
settings.ostr << '(';
|
||||
|
@ -0,0 +1,17 @@
|
||||
SelectWithUnionQuery (children 1)
|
||||
ExpressionList (children 1)
|
||||
SelectQuery (children 1)
|
||||
ExpressionList (children 1)
|
||||
Function tupleElement (children 1)
|
||||
ExpressionList (children 2)
|
||||
Literal UInt64_255
|
||||
Literal UInt64_100
|
||||
SelectWithUnionQuery (children 1)
|
||||
ExpressionList (children 1)
|
||||
SelectQuery (children 1)
|
||||
ExpressionList (children 1)
|
||||
Function tupleElement (children 1)
|
||||
ExpressionList (children 2)
|
||||
Literal Tuple_(UInt64_255, UInt64_1)
|
||||
Literal UInt64_1
|
||||
255
|
@ -0,0 +1,3 @@
|
||||
explain ast select tupleElement(255, 100);
|
||||
explain ast select tupleElement((255, 1), 1);
|
||||
select tupleElement((255, 1), 1);
|
Loading…
Reference in New Issue
Block a user