Skip to content

Commit e48a4a3

Browse files
committed
Parse numbers and timestamps/durations differently (cause they have different data types).
1 parent 19c699a commit e48a4a3

File tree

5 files changed

+447
-351
lines changed

5 files changed

+447
-351
lines changed

src/Core/DecimalFunctions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ inline T multiplyAdd(const T & x, const T & multiplier, const T & delta)
118118
return res;
119119
}
120120

121+
template <typename T>
122+
inline bool tryMultiplyAdd(const T & x, const T & multiplier, const T & delta, T & result)
123+
{
124+
return multiplyAdd<T, false>(x, multiplier, delta, result);
125+
}
126+
121127
/** Make a decimal value from whole and fractional components with given scale multiplier.
122128
* where scale_multiplier = scaleMultiplier<T>(scale)
123129
* this is to reduce number of calls to scaleMultiplier when scale is known.

src/Parsers/Prometheus/PrometheusQueryParsingUtil-antlr.cpp

Lines changed: 23 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#include <Parsers/Prometheus/PrometheusQueryParsingUtil.h>
22

3-
#include <Common/typeid_cast.h>
4-
#include <Core/DecimalFunctions.h>
5-
#include <IO/WriteHelpers.h>
3+
#include <Common/Exception.h>
64

75
#include "config.h"
86

97
#if USE_ANTLR4_GRAMMARS
8+
#include <Parsers/Prometheus/PrometheusQueryTree.h>
9+
1010
#pragma clang diagnostic push
1111
#pragma clang diagnostic ignored "-Wdocumentation"
1212
#pragma clang diagnostic ignored "-Wdocumentation-deprecated-sync"
@@ -151,14 +151,13 @@ namespace
151151
static size_t getStartPos(const antlr4::ParserRuleContext * ctx) { return ctx->start->getStartIndex(); }
152152
static size_t getLength(const antlr4::tree::TerminalNode * ctx) { return ctx->getSymbol()->getStopIndex() - ctx->getSymbol()->getStartIndex() + 1; }
153153
static size_t getLength(const antlr4::ParserRuleContext * ctx) { return ctx->stop->getStopIndex() - ctx->start->getStartIndex() + 1; }
154-
std::string_view getText(const antlr4::tree::TerminalNode * ctx) const { return getText(getStartPos(ctx), getLength(ctx)); }
155-
std::string_view getText(size_t start_pos, size_t length) const { return std::string_view{promql_query}.substr(start_pos, length); }
154+
std::string_view getText(const antlr4::tree::TerminalNode * ctx) const { return std::string_view{promql_query}.substr(getStartPos(ctx), getLength(ctx)); }
156155

157156
bool parseStringLiteral(const antlr4::tree::TerminalNode * ctx, String & result)
158157
{
159158
String error_message;
160159
size_t error_pos;
161-
if (!PrometheusQueryParsingUtil::parseStringLiteral(getText(ctx), result, error_message, error_pos))
160+
if (!PrometheusQueryParsingUtil::tryParseStringLiteral(getText(ctx), result, &error_message, &error_pos))
162161
{
163162
error_listener.setError(error_message, error_pos + getStartPos(ctx));
164163
return false;
@@ -170,116 +169,59 @@ namespace
170169
{
171170
String error_message;
172171
size_t error_pos;
173-
PrometheusQueryParsingUtil::ScalarOrInterval scalar_or_interval;
174-
if (!PrometheusQueryParsingUtil::parseScalarOrInterval(getText(ctx), scalar_or_interval, error_message, error_pos))
172+
if (!PrometheusQueryParsingUtil::tryParseScalar(getText(ctx), result, &error_message, &error_pos))
175173
{
176174
error_listener.setError(error_message, error_pos + getStartPos(ctx));
177175
return false;
178176
}
179-
180-
if (scalar_or_interval.scalar)
181-
{
182-
result = *scalar_or_interval.scalar;
183-
}
184-
else
185-
{
186-
const auto & decimal_field = *scalar_or_interval.interval;
187-
if (!DecimalUtils::tryConvertTo(decimal_field.getValue(), decimal_field.getScale(), result))
188-
{
189-
error_listener.setError(fmt::format("Cannot convert {} to scalar", ::DB::toString(decimal_field.getValue(), decimal_field.getScale())), getStartPos(ctx));
190-
return false;
191-
}
192-
}
193177
return true;
194178
}
195179

196180
bool parseTimestamp(const antlr4::tree::TerminalNode * ctx, TimestampType & result)
197181
{
198-
DurationType duration;
199-
if (!parseDuration(ctx, duration))
182+
String error_message;
183+
size_t error_pos;
184+
if (!PrometheusQueryParsingUtil::tryParseTimestamp(getText(ctx), timestamp_scale, result, &error_message, &error_pos))
185+
{
186+
error_listener.setError(error_message, error_pos + getStartPos(ctx));
200187
return false;
201-
result = static_cast<TimestampType>(duration);
188+
}
202189
return true;
203190
}
204191

205192
bool parseDuration(const antlr4::tree::TerminalNode * ctx, DurationType & result)
206-
{
207-
return parseDuration(getStartPos(ctx), getLength(ctx), result);
208-
}
209-
210-
bool parseDuration(size_t start_pos, size_t length, DurationType & result)
211193
{
212194
String error_message;
213195
size_t error_pos;
214-
PrometheusQueryParsingUtil::ScalarOrInterval scalar_or_interval;
215-
if (!PrometheusQueryParsingUtil::parseScalarOrInterval(getText(start_pos, length), scalar_or_interval, error_message, error_pos))
196+
if (!PrometheusQueryParsingUtil::tryParseDuration(getText(ctx), timestamp_scale, result, &error_message, &error_pos))
216197
{
217-
error_listener.setError(error_message, error_pos + start_pos);
198+
error_listener.setError(error_message, error_pos + getStartPos(ctx));
218199
return false;
219200
}
220-
221-
if (scalar_or_interval.scalar)
222-
{
223-
result = static_cast<Int64>(*scalar_or_interval.scalar * DecimalUtils::scaleMultiplier<Decimal64>(timestamp_scale));
224-
}
225-
else
226-
{
227-
const auto & decimal_field = *scalar_or_interval.interval;
228-
result = DecimalUtils::convertTo<Decimal64>(timestamp_scale, decimal_field.getValue(), decimal_field.getScale());
229-
}
230-
231201
return true;
232202
}
233203

234204
bool parseSelectorRange(const antlr4::tree::TerminalNode * ctx, DurationType & res_range)
235205
{
236-
std::string_view sv = getText(ctx);
237-
238206
String error_message;
239207
size_t error_pos;
240-
std::string_view range_sv;
241-
242-
if (!PrometheusQueryParsingUtil::findTimeRange(sv, range_sv, error_message, error_pos))
208+
if (!PrometheusQueryParsingUtil::tryParseSelectorRange(getText(ctx), timestamp_scale, res_range, &error_message, &error_pos))
243209
{
244210
error_listener.setError(error_message, error_pos + getStartPos(ctx));
245211
return false;
246212
}
247-
248-
size_t range_start_pos = range_sv.data() - promql_query.data();
249-
size_t range_length = range_sv.length();
250-
return parseDuration(range_start_pos, range_length, res_range);
213+
return true;
251214
}
252215

253216
bool parseSubqueryRange(const antlr4::tree::TerminalNode * ctx, DurationType & res_range, std::optional<DurationType> & res_resolution)
254217
{
255-
std::string_view sv = getText(ctx);
256-
257218
String error_message;
258219
size_t error_pos;
259-
std::string_view range_sv;
260-
std::string_view resolution_sv;
261-
262-
if (!PrometheusQueryParsingUtil::findSubqueryRangeAndResolution(sv, range_sv, resolution_sv, error_message, error_pos))
220+
if (!PrometheusQueryParsingUtil::tryParseSubqueryRange(getText(ctx), timestamp_scale, res_range, res_resolution, &error_message, &error_pos))
263221
{
264222
error_listener.setError(error_message, error_pos + getStartPos(ctx));
265223
return false;
266224
}
267-
268-
size_t range_start_pos = range_sv.data() - promql_query.data();
269-
size_t range_length = range_sv.length();
270-
if (!parseDuration(range_start_pos, range_length, res_range))
271-
return false;
272-
273-
res_resolution.reset();
274-
275-
if (!resolution_sv.empty())
276-
{
277-
size_t resolution_start_pos = resolution_sv.data() - promql_query.data();
278-
size_t resolution_length = resolution_sv.length();
279-
if (!parseDuration(resolution_start_pos, resolution_length, res_resolution.emplace()))
280-
return false;
281-
}
282-
283225
return true;
284226
}
285227

@@ -954,7 +896,7 @@ namespace
954896

955897
#endif
956898

957-
bool PrometheusQueryParsingUtil::parseQuery([[maybe_unused]] std::string_view input, [[maybe_unused]] UInt32 timestamp_scale, [[maybe_unused]] PrometheusQueryTree & result, [[maybe_unused]] String & error_message, [[maybe_unused]] size_t & error_pos)
899+
bool PrometheusQueryParsingUtil::tryParseQuery([[maybe_unused]] std::string_view input, [[maybe_unused]] UInt32 timestamp_scale, [[maybe_unused]] PrometheusQueryTree & res_query, [[maybe_unused]] String * error_message, [[maybe_unused]] size_t * error_pos)
958900
{
959901
#if USE_ANTLR4_GRAMMARS
960902
ErrorListener error_listener{input};
@@ -988,15 +930,17 @@ bool PrometheusQueryParsingUtil::parseQuery([[maybe_unused]] std::string_view in
988930

989931
if (error_listener.hasError())
990932
{
991-
error_message = error_listener.getErrorMessage();
992-
error_pos = error_listener.getErrorPos();
933+
if (error_message)
934+
*error_message = error_listener.getErrorMessage();
935+
if (error_pos)
936+
*error_pos = error_listener.getErrorPos();
993937
return false;
994938
}
995939

996940
if (!parsed_root)
997941
throw Exception(ErrorCodes::LOGICAL_ERROR, "Parsing promql query '{}' failed without setting any error message", input);
998942

999-
result = PrometheusQueryTree{String{input}, timestamp_scale, parsed_root, std::move(parsed_nodes)};
943+
res_query = PrometheusQueryTree{String{input}, timestamp_scale, parsed_root, std::move(parsed_nodes)};
1000944
return true;
1001945
#else
1002946
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "ANTLR4 support is disabled");

0 commit comments

Comments
 (0)