Prometheus: Fix parsing of binary operations (#46549)

pull/46601/head
Andrej Ocenas 3 years ago committed by GitHub
parent 04267a66ec
commit a2cec62fa2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 61
      public/app/plugins/datasource/prometheus/querybuilder/parsing.test.ts
  2. 35
      public/app/plugins/datasource/prometheus/querybuilder/parsing.ts

@ -444,6 +444,67 @@ describe('buildVisualQueryFromString', () => {
},
});
});
it('handles multiple binary operations', () => {
expect(buildVisualQueryFromString('foo{x="yy"} * metric{y="zz",a="bb"} * metric2')).toEqual({
errors: [],
query: {
metric: 'foo',
labels: [{ label: 'x', op: '=', value: 'yy' }],
operations: [],
binaryQueries: [
{
operator: '*',
query: {
metric: 'metric',
labels: [
{ label: 'y', op: '=', value: 'zz' },
{ label: 'a', op: '=', value: 'bb' },
],
operations: [],
},
},
{
operator: '*',
query: {
metric: 'metric2',
labels: [],
operations: [],
},
},
],
},
});
});
it('handles multiple binary operations and scalar', () => {
expect(buildVisualQueryFromString('foo{x="yy"} * metric{y="zz",a="bb"} * 2')).toEqual({
errors: [],
query: {
metric: 'foo',
labels: [{ label: 'x', op: '=', value: 'yy' }],
operations: [
{
id: '__multiply_by',
params: [2],
},
],
binaryQueries: [
{
operator: '*',
query: {
metric: 'metric',
labels: [
{ label: 'y', op: '=', value: 'zz' },
{ label: 'a', op: '=', value: 'bb' },
],
operations: [],
},
},
],
},
});
});
});
function noErrors(query: PromVisualQuery) {

@ -350,44 +350,31 @@ function handleBinary(expr: string, node: SyntaxNode, context: Context) {
const leftNumber = left.getChild('NumberLiteral');
const rightNumber = right.getChild('NumberLiteral');
if (leftNumber || rightNumber) {
// Scalar case, just add operation.
if (leftNumber) {
// TODO: this should be already handled in case parent is binary expression as it has to be added to parent
// if query starts with a number that isn't handled now.
} else {
handleExpression(expr, left, context);
}
if (rightNumber) {
// TODO: this should be already handled in case parent is binary expression as it has to be added to parent
// if query starts with a number that isn't handled now.
visQuery.operations.push(makeBinOp(opDef, expr, right, binModifier));
} else {
handleExpression(expr, right, context);
}
return;
}
const leftBinary = left.getChild('BinaryExpr');
const rightBinary = right.getChild('BinaryExpr');
if (leftBinary || rightBinary) {
// One of the sides is binary which means we don't really know if there is a query or just chained scalars. So
if (leftNumber) {
// TODO: this should be already handled in case parent is binary expression as it has to be added to parent
// if query starts with a number that isn't handled now.
} else {
// If this is binary we don't really know if there is a query or just chained scalars. So
// we have to traverse a bit deeper to know
handleExpression(expr, left, context);
}
if (rightNumber) {
visQuery.operations.push(makeBinOp(opDef, expr, right, binModifier));
} else if (rightBinary) {
// Due to the way binary ops are parsed we can get a binary operation on the right that starts with a number which
// is a factor for a current binary operation. So we have to add it as an operation now.
const leftMostChild = getLeftMostChild(right);
if (leftMostChild?.name === 'NumberLiteral') {
visQuery.operations.push(makeBinOp(opDef, expr, leftMostChild, binModifier));
}
// If we added the first number literal as operation here we still can continue and handle the rest as the first
// number will be just skipped.
handleExpression(expr, right, context);
} else {
// Two queries case so we create a binary query.
visQuery.binaryQueries = visQuery.binaryQueries || [];
const binQuery = {
operator: op,
@ -398,8 +385,6 @@ function handleBinary(expr: string, node: SyntaxNode, context: Context) {
},
};
visQuery.binaryQueries.push(binQuery);
// One query is the main query, second is wrapped in the binaryQuery wrapper.
handleExpression(expr, left, context);
handleExpression(expr, right, {
query: binQuery.query,
errors: context.errors,

Loading…
Cancel
Save