[bugfix] Parse negative value in PromQL (#4564)

* Parse negative value in PromQL
* Enforce space between values

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
This commit is contained in:
Ganesh Vernekar 2018-09-13 13:38:01 +05:30 committed by Brian Brazil
parent 068eaa5dbf
commit 73db8b8cea
4 changed files with 60 additions and 1 deletions

View File

@ -143,6 +143,7 @@ const (
itemDuration
itemBlank
itemTimes
itemSpace
operatorsStart
// Operators.
@ -247,6 +248,7 @@ var itemTypeStr = map[ItemType]string{
itemSemicolon: ";",
itemBlank: "_",
itemTimes: "x",
itemSpace: "<space>",
itemSUB: "-",
itemADD: "+",
@ -616,6 +618,7 @@ func lexValueSequence(l *lexer) stateFn {
case r == eof:
return lexStatements
case isSpace(r):
l.emit(itemSpace)
lexSpace(l)
case r == '+':
l.emit(itemADD)

View File

@ -406,9 +406,13 @@ var tests = []struct {
expected: []item{
{itemLeftBrace, 0, `{`},
{itemRightBrace, 1, `}`},
{itemSpace, 2, ` `},
{itemBlank, 3, `_`},
{itemSpace, 4, ` `},
{itemNumber, 5, `1`},
{itemSpace, 6, ` `},
{itemTimes, 7, `x`},
{itemSpace, 8, ` `},
{itemNumber, 9, `.3`},
},
seriesDesc: true,
@ -417,9 +421,12 @@ var tests = []struct {
input: `metric +Inf Inf NaN`,
expected: []item{
{itemIdentifier, 0, `metric`},
{itemSpace, 6, ` `},
{itemADD, 7, `+`},
{itemNumber, 8, `Inf`},
{itemSpace, 11, ` `},
{itemNumber, 12, `Inf`},
{itemSpace, 15, ` `},
{itemNumber, 16, `NaN`},
},
seriesDesc: true,
@ -428,6 +435,7 @@ var tests = []struct {
input: `metric 1+1x4`,
expected: []item{
{itemIdentifier, 0, `metric`},
{itemSpace, 6, ` `},
{itemNumber, 7, `1`},
{itemADD, 8, `+`},
{itemNumber, 9, `1`},

View File

@ -175,6 +175,9 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
const ctx = "series values"
for {
for p.peek().typ == itemSpace {
p.next()
}
if p.peek().typ == itemEOF {
break
}
@ -193,6 +196,11 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
for i := uint64(0); i < times; i++ {
vals = append(vals, sequenceValue{omitted: true})
}
// This is to ensure that there is a space between this and the next number.
// This is especially required if the next number is negative.
if t := p.expectOneOf(itemSpace, itemEOF, ctx).typ; t == itemEOF {
break
}
continue
}
@ -217,7 +225,8 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
})
// If there are no offset repetitions specified, proceed with the next value.
if t := p.peek(); t.typ == itemNumber || t.typ == itemBlank || t.typ == itemIdentifier && t.val == "stale" {
if t := p.peek(); t.typ == itemSpace {
// This ensures there is a space between every value.
continue
} else if t.typ == itemEOF {
break
@ -244,6 +253,12 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
value: k,
})
}
// This is to ensure that there is a space between this expanding notation
// and the next number. This is especially required if the next number
// is negative.
if t := p.expectOneOf(itemSpace, itemEOF, ctx).typ; t == itemEOF {
break
}
}
return m, vals, nil
}

View File

@ -1737,6 +1737,39 @@ var testSeries = []struct {
}, {
input: `my_metric{a="b"} 1 3 _ 5 _a4`,
fail: true,
}, {
input: `my_metric{a="b"} 1 -1`,
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
expectedValues: newSeq(1, -1),
}, {
input: `my_metric{a="b"} 1 +1`,
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
expectedValues: newSeq(1, 1),
}, {
input: `my_metric{a="b"} 1 -1 -3-10x4 7 9 +5`,
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
expectedValues: newSeq(1, -1, -3, -13, -23, -33, -43, 7, 9, 5),
}, {
input: `my_metric{a="b"} 1 +1 +4 -6 -2 8`,
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
expectedValues: newSeq(1, 1, 4, -6, -2, 8),
}, {
// Trailing spaces should be correctly handles.
input: `my_metric{a="b"} 1 2 3 `,
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
expectedValues: newSeq(1, 2, 3),
}, {
input: `my_metric{a="b"} -3-3 -3`,
fail: true,
}, {
input: `my_metric{a="b"} -3 -3-3`,
fail: true,
}, {
input: `my_metric{a="b"} -3 _-2`,
fail: true,
}, {
input: `my_metric{a="b"} -3 3+3x4-4`,
fail: true,
},
}