mirror of
https://github.com/prometheus/prometheus.git
synced 2026-02-03 20:39:32 -05:00
Merge 147a28dff5 into 02c68154bc
This commit is contained in:
commit
e0e4aa401a
4 changed files with 140 additions and 0 deletions
|
|
@ -599,6 +599,13 @@ matrix_selector : expr LEFT_BRACKET positive_duration_expr RIGHT_BRACKET
|
|||
|
||||
subquery_expr : expr LEFT_BRACKET positive_duration_expr COLON positive_duration_expr RIGHT_BRACKET
|
||||
{
|
||||
// Check if offset/@ modifiers are immediately before the subquery brackets.
|
||||
hasModifiers, errMsg := yylex.(*parser).hasModifiersBeforeRange($1.(Expr), $2.Pos)
|
||||
if hasModifiers {
|
||||
errRange := mergeRanges(&$2, &$6)
|
||||
yylex.(*parser).addParseErrf(errRange, "%s", errMsg)
|
||||
}
|
||||
|
||||
var rangeNl time.Duration
|
||||
var stepNl time.Duration
|
||||
if numLit, ok := $3.(*NumberLiteral); ok {
|
||||
|
|
@ -620,6 +627,13 @@ subquery_expr : expr LEFT_BRACKET positive_duration_expr COLON positive_durati
|
|||
}
|
||||
| expr LEFT_BRACKET positive_duration_expr COLON RIGHT_BRACKET
|
||||
{
|
||||
// Check if offset/@ modifiers are immediately before the subquery brackets.
|
||||
hasModifiers, errMsg := yylex.(*parser).hasModifiersBeforeRange($1.(Expr), $2.Pos)
|
||||
if hasModifiers {
|
||||
errRange := mergeRanges(&$2, &$5)
|
||||
yylex.(*parser).addParseErrf(errRange, "%s", errMsg)
|
||||
}
|
||||
|
||||
var rangeNl time.Duration
|
||||
if numLit, ok := $3.(*NumberLiteral); ok {
|
||||
rangeNl = time.Duration(math.Round(numLit.Val*float64(time.Second)))
|
||||
|
|
|
|||
|
|
@ -1594,6 +1594,13 @@ yydefault:
|
|||
case 90:
|
||||
yyDollar = yyS[yypt-6 : yypt+1]
|
||||
{
|
||||
// Check if offset/@ modifiers are immediately before the subquery brackets.
|
||||
hasModifiers, errMsg := yylex.(*parser).hasModifiersBeforeRange(yyDollar[1].node.(Expr), yyDollar[2].item.Pos)
|
||||
if hasModifiers {
|
||||
errRange := mergeRanges(&yyDollar[2].item, &yyDollar[6].item)
|
||||
yylex.(*parser).addParseErrf(errRange, "%s", errMsg)
|
||||
}
|
||||
|
||||
var rangeNl time.Duration
|
||||
var stepNl time.Duration
|
||||
if numLit, ok := yyDollar[3].node.(*NumberLiteral); ok {
|
||||
|
|
@ -1616,6 +1623,13 @@ yydefault:
|
|||
case 91:
|
||||
yyDollar = yyS[yypt-5 : yypt+1]
|
||||
{
|
||||
// Check if offset/@ modifiers are immediately before the subquery brackets.
|
||||
hasModifiers, errMsg := yylex.(*parser).hasModifiersBeforeRange(yyDollar[1].node.(Expr), yyDollar[2].item.Pos)
|
||||
if hasModifiers {
|
||||
errRange := mergeRanges(&yyDollar[2].item, &yyDollar[5].item)
|
||||
yylex.(*parser).addParseErrf(errRange, "%s", errMsg)
|
||||
}
|
||||
|
||||
var rangeNl time.Duration
|
||||
if numLit, ok := yyDollar[3].node.(*NumberLiteral); ok {
|
||||
rangeNl = time.Duration(math.Round(numLit.Val * float64(time.Second)))
|
||||
|
|
|
|||
|
|
@ -1191,6 +1191,49 @@ func (p *parser) getAtModifierVars(e Node) (**int64, *ItemType, *posrange.Pos, b
|
|||
return timestampp, preprocp, endPosp, true
|
||||
}
|
||||
|
||||
// hasModifiersBeforeRange checks if an expression has offset/@ modifiers that are
|
||||
// immediately adjacent to a bracket (no space), which should be rejected for subqueries.
|
||||
func (*parser) hasModifiersBeforeRange(expr Expr, bracketPos posrange.Pos) (bool, string) {
|
||||
var endPos posrange.Pos
|
||||
var hasOffset bool
|
||||
var hasAtModifier bool
|
||||
|
||||
switch e := expr.(type) {
|
||||
case *VectorSelector:
|
||||
endPos = e.PosRange.End
|
||||
hasOffset = e.OriginalOffset != 0 || e.OriginalOffsetExpr != nil
|
||||
hasAtModifier = e.Timestamp != nil
|
||||
case *MatrixSelector:
|
||||
vs, ok := e.VectorSelector.(*VectorSelector)
|
||||
if !ok {
|
||||
return false, ""
|
||||
}
|
||||
endPos = e.EndPos
|
||||
hasOffset = vs.OriginalOffset != 0 || vs.OriginalOffsetExpr != nil
|
||||
hasAtModifier = vs.Timestamp != nil
|
||||
case *SubqueryExpr:
|
||||
endPos = e.EndPos
|
||||
hasOffset = e.OriginalOffset != 0 || e.OriginalOffsetExpr != nil
|
||||
hasAtModifier = e.Timestamp != nil
|
||||
default:
|
||||
// Other expression types (function calls, binary ops, etc.) don't have modifiers
|
||||
// at the selector level, so they're fine.
|
||||
return false, ""
|
||||
}
|
||||
|
||||
// Check if modifiers exist and are adjacent to the bracket (no space)
|
||||
if endPos == bracketPos {
|
||||
if hasOffset {
|
||||
return true, "no offset modifiers allowed before range"
|
||||
}
|
||||
if hasAtModifier {
|
||||
return true, "no @ modifiers allowed before range"
|
||||
}
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func (p *parser) experimentalDurationExpr(e Expr) {
|
||||
if !ExperimentalDurationExpr {
|
||||
p.addParseErrf(e.PositionRange(), "experimental duration expression is not enabled")
|
||||
|
|
|
|||
|
|
@ -2779,6 +2779,75 @@ var testExpr = []struct {
|
|||
},
|
||||
},
|
||||
},
|
||||
// Test subquery: offset/@ modifiers immediately before subquery brackets (should error)
|
||||
{
|
||||
input: `some_metric offset 5m[2m:10s]`,
|
||||
fail: true,
|
||||
errors: ParseErrors{
|
||||
ParseErr{
|
||||
PositionRange: posrange.PositionRange{Start: 21, End: 29},
|
||||
Err: errors.New("no offset modifiers allowed before range"),
|
||||
Query: `some_metric offset 5m[2m:10s]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `some_metric @ 123[2m:10s]`,
|
||||
fail: true,
|
||||
errors: ParseErrors{
|
||||
ParseErr{
|
||||
PositionRange: posrange.PositionRange{Start: 17, End: 25},
|
||||
Err: errors.New("no @ modifiers allowed before range"),
|
||||
Query: `some_metric @ 123[2m:10s]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// Test subquery: matrix selector with offset/@ before subquery (should error)
|
||||
{
|
||||
input: `some_metric[5m] offset 1m[2m:10s]`,
|
||||
fail: true,
|
||||
errors: ParseErrors{
|
||||
ParseErr{
|
||||
PositionRange: posrange.PositionRange{Start: 25, End: 33},
|
||||
Err: errors.New("no offset modifiers allowed before range"),
|
||||
Query: `some_metric[5m] offset 1m[2m:10s]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `some_metric[5m] @ 123[2m:10s]`,
|
||||
fail: true,
|
||||
errors: ParseErrors{
|
||||
ParseErr{
|
||||
PositionRange: posrange.PositionRange{Start: 21, End: 29},
|
||||
Err: errors.New("no @ modifiers allowed before range"),
|
||||
Query: `some_metric[5m] @ 123[2m:10s]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// Test subquery: nested subquery with offset/@ before outer subquery (should error)
|
||||
{
|
||||
input: `some_metric[2m:10s] offset 1m[5m:1m]`,
|
||||
fail: true,
|
||||
errors: ParseErrors{
|
||||
ParseErr{
|
||||
PositionRange: posrange.PositionRange{Start: 29, End: 36},
|
||||
Err: errors.New("no offset modifiers allowed before range"),
|
||||
Query: `some_metric[2m:10s] offset 1m[5m:1m]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `some_metric[2m:10s] @ 123[5m:1m]`,
|
||||
fail: true,
|
||||
errors: ParseErrors{
|
||||
ParseErr{
|
||||
PositionRange: posrange.PositionRange{Start: 25, End: 32},
|
||||
Err: errors.New("no @ modifiers allowed before range"),
|
||||
Query: `some_metric[2m:10s] @ 123[5m:1m]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `(foo + bar)[5m]`,
|
||||
fail: true,
|
||||
|
|
|
|||
Loading…
Reference in a new issue