Example #1
0
static bool parseDecimal(IParser::Pos & pos, IParser::Pos end, ASTSampleRatio::Rational & res, IParser::Pos & max_parsed_pos)
{
    ParserWhitespaceOrComments ws;
    ws.ignore(pos, end);

    UInt64 num_before = 0;
    UInt64 num_after = 0;
    Int64 exponent = 0;

    IParser::Pos pos_after_first_num = tryReadIntText(num_before, pos, end);

    bool has_num_before_point = pos_after_first_num > pos;
    pos = pos_after_first_num;
    bool has_point = pos < end && *pos == '.';

    if (has_point)
        ++pos;

    if (!has_num_before_point && !has_point)
        return false;

    size_t number_of_digits_after_point = 0;

    if (has_point)
    {
        IParser::Pos pos_after_second_num = tryReadIntText(num_after, pos, end);
        number_of_digits_after_point = pos_after_second_num - pos;
        pos = pos_after_second_num;
    }

    bool has_exponent = pos < end && (*pos == 'e' || *pos == 'E');

    if (has_exponent)
    {
        ++pos;
        IParser::Pos pos_after_exponent = tryReadIntText(exponent, pos, end);

        if (pos_after_exponent == pos)
            return false;

        pos = pos_after_exponent;
    }

    res.numerator = num_before * exp10(number_of_digits_after_point) + num_after;
    res.denominator = exp10(number_of_digits_after_point);

    if (exponent > 0)
        res.numerator *= exp10(exponent);
    if (exponent < 0)
        res.denominator *= exp10(-exponent);

    /// NOTE You do not need to remove the common power of ten from the numerator and denominator.
    return true;
}
Example #2
0
/** Possible options:
  *
  * 12345
  * - an integer
  *
  * 0.12345
  * .12345
  * 0.
  * - fraction in ordinary decimal notation
  *
  * 1.23e-1
  * - fraction in scientific decimal notation
  *
  * 123 / 456
  * - fraction with an ordinary denominator
  *
  * Just in case, in the numerator and denominator of the fraction, we support the previous cases.
  * Example:
  * 123.0 / 456e0
  */
bool ParserSampleRatio::parseImpl(IParser::Pos & pos, IParser::Pos end, ASTPtr & node, IParser::Pos & max_parsed_pos, Expected & expected)
{
    auto begin = pos;

    ParserWhitespaceOrComments ws;

    ASTSampleRatio::Rational numerator;
    ASTSampleRatio::Rational denominator;
    ASTSampleRatio::Rational res;

    ws.ignore(pos, end);

    if (!parseDecimal(pos, end, numerator, max_parsed_pos))
        return false;

    ws.ignore(pos, end);

    bool has_slash = pos < end && *pos == '/';

    if (has_slash)
    {
        ++pos;
        ws.ignore(pos, end);

        if (!parseDecimal(pos, end, denominator, max_parsed_pos))
            return false;

        res.numerator = numerator.numerator * denominator.denominator;
        res.denominator = numerator.denominator * denominator.numerator;
    }
    else
    {
        res = numerator;
    }

    ws.ignore(pos, end);

    node = std::make_shared<ASTSampleRatio>(StringRange(begin, pos), res);
    return true;
}
Example #3
0
bool ParserTablePropertiesQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
{
    Pos begin = pos;

    ParserWhitespaceOrComments ws;
    ParserKeyword s_exists("EXISTS");
    ParserKeyword s_describe("DESCRIBE");
    ParserKeyword s_desc("DESC");
    ParserKeyword s_show("SHOW");
    ParserKeyword s_create("CREATE");
    ParserKeyword s_table("TABLE");
    ParserString s_dot(".");
    ParserIdentifier name_p;

    ASTPtr database;
    ASTPtr table;
    std::shared_ptr<ASTQueryWithTableAndOutput> query;

    ws.ignore(pos, end);

    if (s_exists.ignore(pos, end, max_parsed_pos, expected))
    {
        query = std::make_shared<ASTExistsQuery>();
    }
    else if (s_describe.ignore(pos, end, max_parsed_pos, expected) || s_desc.ignore(pos, end, max_parsed_pos, expected))
    {
        query = std::make_shared<ASTDescribeQuery>();
    }
    else if (s_show.ignore(pos, end, max_parsed_pos, expected))
    {
        ws.ignore(pos, end);

        if (!s_create.ignore(pos, end, max_parsed_pos, expected))
            return false;

        query = std::make_shared<ASTShowCreateQuery>();
    }
    else
    {
        return false;
    }

    ws.ignore(pos, end);

    s_table.ignore(pos, end, max_parsed_pos, expected);

    ws.ignore(pos, end);

    if (!name_p.parse(pos, end, table, max_parsed_pos, expected))
        return false;

    ws.ignore(pos, end);

    if (s_dot.ignore(pos, end, max_parsed_pos, expected))
    {
        database = table;
        if (!name_p.parse(pos, end, table, max_parsed_pos, expected))
            return false;

        ws.ignore(pos, end);
    }

    ws.ignore(pos, end);

    query->range = StringRange(begin, pos);

    if (database)
        query->database = typeid_cast<ASTIdentifier &>(*database).name;
    if (table)
        query->table = typeid_cast<ASTIdentifier &>(*table).name;

    node = query;

    return true;
}
Example #4
0
bool ParserAlterQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
{
    Pos begin = pos;

    ParserKeyword s_alter_table("ALTER TABLE");
    ParserKeyword s_add_column("ADD COLUMN");
    ParserKeyword s_drop_column("DROP COLUMN");
    ParserKeyword s_modify_column("MODIFY COLUMN");
    ParserKeyword s_modify_primary_key("MODIFY PRIMARY KEY");

    ParserKeyword s_attach_partition("ATTACH PARTITION");
    ParserKeyword s_detach_partition("DETACH PARTITION");
    ParserKeyword s_drop_partition("DROP PARTITION");
    ParserKeyword s_attach_part("ATTACH PART");
    ParserKeyword s_fetch_partition("FETCH PARTITION");
    ParserKeyword s_freeze_partition("FREEZE PARTITION");
    ParserKeyword s_reshard("RESHARD");
    ParserKeyword s_partition("PARTITION");

    ParserKeyword s_after("AFTER");
    ParserKeyword s_from("FROM");
    ParserKeyword s_from_partition("FROM PARTITION");
    ParserKeyword s_copy("COPY");
    ParserKeyword s_to("TO");
    ParserKeyword s_using("USING");
    ParserKeyword s_coordinate("COORDINATE");
    ParserKeyword s_with("WITH");
    ParserKeyword s_name("NAME");

    ParserString s_dot(".");
    ParserString s_comma(",");
    ParserString s_doubledot("..");

    ParserWhitespaceOrComments ws;

    ParserIdentifier table_parser;
    ParserCompoundIdentifier parser_name;
    ParserCompoundColumnDeclaration parser_col_decl;
    ParserLiteral parser_literal;
    ParserUnsignedInteger parser_uint;
    ParserStringLiteral parser_string_literal;

    ASTPtr table;
    ASTPtr database;
    String cluster_str;
    ASTPtr col_type;
    ASTPtr col_after;
    ASTPtr col_drop;

    auto query = std::make_shared<ASTAlterQuery>();

    ws.ignore(pos, end);
    if (!s_alter_table.ignore(pos, end, max_parsed_pos, expected))
        return false;

    ws.ignore(pos, end);

    if (!table_parser.parse(pos, end, database, max_parsed_pos, expected))
        return false;

    /// Parse [db].name
    if (s_dot.ignore(pos, end))
    {
        if (!table_parser.parse(pos, end, table, max_parsed_pos, expected))
            return false;

        query->table = typeid_cast<ASTIdentifier &>(*table).name;
        query->database = typeid_cast<ASTIdentifier &>(*database).name;
    }
    else
    {
        table = database;
        query->table = typeid_cast<ASTIdentifier &>(*table).name;
    }

    ws.ignore(pos, end);

    if (ParserKeyword{"ON"}.ignore(pos, end, max_parsed_pos, expected))
    {
        if (!ASTQueryWithOnCluster::parse(pos, end, cluster_str, max_parsed_pos, expected))
            return false;
    }

    bool parsing_finished = false;
    do
    {
        ASTAlterQuery::Parameters params;
        ws.ignore(pos, end);

        if (s_add_column.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_col_decl.parse(pos, end, params.col_decl, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);
            if (s_after.ignore(pos, end, max_parsed_pos, expected))
            {
                ws.ignore(pos, end);

                if(!parser_name.parse(pos, end, params.column, max_parsed_pos, expected))
                    return false;
            }

            params.type = ASTAlterQuery::ADD_COLUMN;
        }
        else if (s_drop_partition.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected))
                return false;

            params.type = ASTAlterQuery::DROP_PARTITION;
        }
        else if (s_drop_column.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_name.parse(pos, end, params.column, max_parsed_pos, expected))
                return false;

            params.type = ASTAlterQuery::DROP_COLUMN;
            params.detach = false;

            if (s_from_partition.ignore(pos, end, max_parsed_pos, expected))
            {
                ws.ignore(pos, end);

                if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected))
                    return false;
            }
        }
        else if (s_detach_partition.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected))
                return false;

            params.type = ASTAlterQuery::DROP_PARTITION;
            params.detach = true;
        }
        else if (s_attach_partition.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected))
                return false;

            params.type = ASTAlterQuery::ATTACH_PARTITION;
        }
        else if (s_attach_part.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected))
                return false;

            params.part = true;
            params.type = ASTAlterQuery::ATTACH_PARTITION;
        }
        else if (s_fetch_partition.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            if (!s_from.ignore(pos, end, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            ASTPtr ast_from;
            if (!parser_string_literal.parse(pos, end, ast_from, max_parsed_pos, expected))
                return false;

            params.from = typeid_cast<const ASTLiteral &>(*ast_from).value.get<const String &>();
            params.type = ASTAlterQuery::FETCH_PARTITION;
        }
        else if (s_freeze_partition.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            /// WITH NAME 'name' - place local backup to directory with specified name
            if (s_with.ignore(pos, end, max_parsed_pos, expected))
            {
                ws.ignore(pos, end);

                if (!s_name.ignore(pos, end, max_parsed_pos, expected))
                    return false;

                ws.ignore(pos, end);

                ASTPtr ast_with_name;
                if (!parser_string_literal.parse(pos, end, ast_with_name, max_parsed_pos, expected))
                    return false;

                params.with_name = typeid_cast<const ASTLiteral &>(*ast_with_name).value.get<const String &>();

                ws.ignore(pos, end);
            }

            params.type = ASTAlterQuery::FREEZE_PARTITION;
        }
        else if (s_modify_column.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!parser_col_decl.parse(pos, end, params.col_decl, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            params.type = ASTAlterQuery::MODIFY_COLUMN;
        }
        else if (s_modify_primary_key.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);

            if (!ParserString("(").ignore(pos, end, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            if (!ParserNotEmptyExpressionList(false).parse(pos, end, params.primary_key, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            if (!ParserString(")").ignore(pos, end, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            params.type = ASTAlterQuery::MODIFY_PRIMARY_KEY;
        }
        else if (s_reshard.ignore(pos, end, max_parsed_pos, expected))
        {
            ParserList weighted_zookeeper_paths_p(std::make_unique<ParserWeightedZooKeeperPath>(), std::make_unique<ParserString>(","), false);
            ParserExpressionWithOptionalAlias parser_sharding_key_expr(false);
            ParserStringLiteral parser_coordinator;

            ws.ignore(pos, end);

            if (s_copy.ignore(pos, end, max_parsed_pos, expected))
                params.do_copy = true;

            ws.ignore(pos, end);

            if (s_partition.ignore(pos, end, max_parsed_pos, expected))
            {
                ws.ignore(pos, end);

                if (!parser_uint.parse(pos, end, params.partition, max_parsed_pos, expected))
                    return false;

                ws.ignore(pos, end);

                if (s_doubledot.ignore(pos, end, max_parsed_pos, expected))
                {
                    ws.ignore(pos, end);

                    if (!parser_uint.parse(pos, end, params.last_partition, max_parsed_pos, expected))
                        return false;
                }
            }

            ws.ignore(pos, end);

            if (!s_to.ignore(pos, end, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            if (!weighted_zookeeper_paths_p.parse(pos, end, params.weighted_zookeeper_paths, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            if (!s_using.ignore(pos, end, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            if (!parser_sharding_key_expr.parse(pos, end, params.sharding_key_expr, max_parsed_pos, expected))
                return false;

            ws.ignore(pos, end);

            if (s_coordinate.ignore(pos, end, max_parsed_pos, expected))
            {
                ws.ignore(pos, end);

                if (!s_with.ignore(pos, end, max_parsed_pos, expected))
                    return false;

                ws.ignore(pos, end);

                if (!parser_coordinator.parse(pos, end, params.coordinator, max_parsed_pos, expected))
                    return false;

                ws.ignore(pos, end);
            }

            params.type = ASTAlterQuery::RESHARD_PARTITION;
        }
        else
            return false;

        ws.ignore(pos, end);

        if (!s_comma.ignore(pos, end, max_parsed_pos, expected))
        {
            ws.ignore(pos, end);
            parsing_finished = true;
        }

        query->addParameters(params);
    }
    while (!parsing_finished);

    query->range = StringRange(begin, end);
    query->cluster = cluster_str;
    node = query;

    return true;
}
Example #5
0
bool ParserInsertQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
{
    Pos begin = pos;

    ParserWhitespaceOrComments ws;
    ParserKeyword s_insert_into("INSERT INTO");
    ParserKeyword s_dot(".");
    ParserKeyword s_values("VALUES");
    ParserKeyword s_format("FORMAT");
    ParserKeyword s_select("SELECT");
    ParserKeyword s_lparen("(");
    ParserKeyword s_rparen(")");
    ParserIdentifier name_p;
    ParserList columns_p(std::make_unique<ParserCompoundIdentifier>(), std::make_unique<ParserString>(","), false);

    ASTPtr database;
    ASTPtr table;
    ASTPtr columns;
    ASTPtr format;
    ASTPtr select;
    /// Insertion data
    const char * data = nullptr;

    ws.ignore(pos, end);

    if (!s_insert_into.ignore(pos, end, max_parsed_pos, expected))
        return false;

    ws.ignore(pos, end);

    if (!name_p.parse(pos, end, table, max_parsed_pos, expected))
        return false;

    ws.ignore(pos, end);

    if (s_dot.ignore(pos, end, max_parsed_pos, expected))
    {
        database = table;
        if (!name_p.parse(pos, end, table, max_parsed_pos, expected))
            return false;

        ws.ignore(pos, end);
    }

    ws.ignore(pos, end);

    /// Is there a list of columns
    if (s_lparen.ignore(pos, end, max_parsed_pos, expected))
    {
        ws.ignore(pos, end);

        if (!columns_p.parse(pos, end, columns, max_parsed_pos, expected))
            return false;

        ws.ignore(pos, end);

        if (!s_rparen.ignore(pos, end, max_parsed_pos, expected))
            return false;
    }

    ws.ignore(pos, end);

    Pos before_select = pos;

    /// VALUES or FORMAT or SELECT
    if (s_values.ignore(pos, end, max_parsed_pos, expected))
    {
        ws.ignore(pos, end);
        data = pos;
        pos = end;
    }
    else if (s_format.ignore(pos, end, max_parsed_pos, expected))
    {
        ws.ignore(pos, end);

        if (!name_p.parse(pos, end, format, max_parsed_pos, expected))
            return false;

        /// Data starts after the first newline, if there is one, or after all the whitespace characters, otherwise.
        ParserWhitespaceOrComments ws_without_nl(false);

        ws_without_nl.ignore(pos, end);
        if (pos != end && *pos == ';')
            throw Exception("You have excessive ';' symbol before data for INSERT.\n"
                "Example:\n\n"
                "INSERT INTO t (x, y) FORMAT TabSeparated\n"
                "1\tHello\n"
                "2\tWorld\n"
                "\n"
                "Note that there is no ';' in first line.", ErrorCodes::SYNTAX_ERROR);

        if (pos != end && *pos == '\n')
            ++pos;

        data = pos;
        pos = end;
    }
    else if (s_select.ignore(pos, end, max_parsed_pos, expected))
    {
        pos = before_select;
        ParserSelectQuery select_p;
        select_p.parse(pos, end, select, max_parsed_pos, expected);
    }
    else
    {
        expected = "VALUES or FORMAT or SELECT";
        return false;
    }

    auto query = std::make_shared<ASTInsertQuery>(StringRange(begin, data ? data : pos));
    node = query;

    if (database)
        query->database = typeid_cast<ASTIdentifier &>(*database).name;

    query->table = typeid_cast<ASTIdentifier &>(*table).name;

    if (format)
        query->format = typeid_cast<ASTIdentifier &>(*format).name;

    query->columns = columns;
    query->select = select;
    query->data = data != end ? data : NULL;
    query->end = end;

    if (columns)
        query->children.push_back(columns);
    if (select)
        query->children.push_back(select);

    return true;
}