aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Functions/JSONPath/Parsers/ParserJSONPathRange.cpp
blob: 03c006774c02d2bdcca4345c0deb173a799053fd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <Functions/JSONPath/ASTs/ASTJSONPathRange.h>
#include <Functions/JSONPath/Parsers/ParserJSONPathQuery.h>
#include <Functions/JSONPath/Parsers/ParserJSONPathRange.h>

#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ExpressionElementParsers.h>
#include <Parsers/CommonParsers.h>

namespace DB
{
namespace ErrorCodes
{
    extern const int BAD_ARGUMENTS;
}
/**
 *
 * @param pos token iterator
 * @param node node of ASTJSONPathQuery
 * @param expected stuff for logging
 * @return was parse successful
 */
bool ParserJSONPathRange::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{

    if (pos->type != TokenType::OpeningSquareBracket)
    {
        return false;
    }
    ++pos;

    auto range = std::make_shared<ASTJSONPathRange>();
    node = range;

    ParserNumber number_p;
    ASTPtr number_ptr;
    while (pos->type != TokenType::ClosingSquareBracket)
    {
        if (pos->type != TokenType::Number)
        {
            return false;
        }

        std::pair<UInt32, UInt32> range_indices;
        if (!number_p.parse(pos, number_ptr, expected))
        {
            return false;
        }
        range_indices.first = static_cast<UInt32>(number_ptr->as<ASTLiteral>()->value.get<UInt32>());

        if (pos->type == TokenType::Comma || pos->type == TokenType::ClosingSquareBracket)
        {
            /// Single index case
            range_indices.second = range_indices.first + 1;
        }
        else if (pos->type == TokenType::BareWord)
        {
            if (!ParserKeyword("TO").ignore(pos, expected))
            {
                return false;
            }
            if (!number_p.parse(pos, number_ptr, expected))
            {
                return false;
            }
            range_indices.second = static_cast<UInt32>(number_ptr->as<ASTLiteral>()->value.get<UInt32>());
        }
        else
        {
            return false;
        }

        if (range_indices.first >= range_indices.second)
        {
            throw Exception(
                ErrorCodes::BAD_ARGUMENTS,
                "Start of range must be greater than end of range, however {} >= {}",
                range_indices.first,
                range_indices.second);
        }

        range->ranges.push_back(std::move(range_indices));
        if (pos->type != TokenType::ClosingSquareBracket)
        {
            ++pos;
        }
    }
    ++pos;

    /// We can't have both ranges and star present, so parse was successful <=> exactly 1 of these conditions is true
    return !range->ranges.empty() ^ range->is_star;
}

}