```
$ clickhouse client
ClickHouse client version 20.10.1.1-arcadia.
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 20.10.1 revision 54441.

max42-dev.sas.yp-c.yandex.net :) create table T(f Array(Tuple(key String, value UInt8))) engine = Log()

Syntax error: failed at position 34 ('String'):

create table T(f Array(Tuple(key String, value UInt8))) engine = Log()

Expected one of: LIKE, GLOBAL NOT IN, AS, IS, OR, QuestionMark, BETWEEN, NOT LIKE, AND, Comma, alias, IN, ILIKE, Dot, NOT ILIKE, NOT, Arrow, NOT IN, token, GLOBAL IN

max42-dev.sas.yp-c.yandex.net :) create table T(f Array(Tuple(String, UInt8))) engine = Log()                  

CREATE TABLE T
(
    `f` Array(Tuple(String, UInt8))
)
ENGINE = Log()

Ok.

0 rows in set. Elapsed: 0.008 sec. 

max42-dev.sas.yp-c.yandex.net :) create table T2(f Tuple(key String, value UInt8)) engine = Log()

CREATE TABLE T2
(
    `f` Tuple(    key String,     value UInt8)
)
ENGINE = Log()

Ok.

0 rows in set. Elapsed: 0.005 sec. 
```

If I understand correctly, DataType parser allows parsing of nested-like data type specifications (i.e. Typename(f1 T1, f2 T2, ...)) only at the top-level. It makes impossible to enclose named tuple into any kind of other structure, like Array or another Tuple. 

Such option is needed for proper interoperability with third-party applications which impose such data types.
{
        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)
    {