EQL: implement math functions: add, divide, module, multiply, subtract#55137
EQL: implement math functions: add, divide, module, multiply, subtract#55137aleksmaus merged 7 commits intoelastic:masterfrom
Conversation
...n/eql/src/main/java/org/elasticsearch/xpack/eql/expression/function/EqlFunctionRegistry.java
Outdated
Show resolved
Hide resolved
...in/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Arithmetics.java
Outdated
Show resolved
Hide resolved
|
and of course QL tests fail with and Will reach out tomorrow. |
|
Pinging @elastic/es-ql (:Query Languages/EQL) |
imotov
left a comment
There was a problem hiding this comment.
The division by 0 exception currently look like this:
{
"error" : {
"root_cause" : [
{
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics.div(Arithmetics.java:100)",
"org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics$NumericArithmetic.wrap(Arithmetics.java:30)",
"org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.DefaultBinaryArithmeticOperation.doApply(DefaultBinaryArithmeticOperation.java:45)",
"org.elasticsearch.xpack.ql.expression.predicate.PredicateBiFunction.apply(PredicateBiFunction.java:24)",
"org.elasticsearch.xpack.ql.expression.function.scalar.whitelist.InternalQlScriptUtils.div(InternalQlScriptUtils.java:128)",
"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(InternalQlScriptUtils.div(params.v0,InternalQlScriptUtils.docValue(doc,params.v1)),params.v2))",
" ^---- HERE"
],
"script" : "InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(InternalQlScriptUtils.div(params.v0,InternalQlScriptUtils.docValue(doc,params.v1)),params.v2))",
"lang" : "painless",
"position" : {
"offset" : 119,
"start" : 0,
"end" : 156
}
}
],
"type" : "search_phase_execution_exception",
"reason" : "all shards failed",
"phase" : "query",
"grouped" : true,
"failed_shards" : [
{
"shard" : 0,
"index" : "endgame",
"node" : "hOOT6db-REOOt2zKF-eYRQ",
"reason" : {
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics.div(Arithmetics.java:100)",
"org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics$NumericArithmetic.wrap(Arithmetics.java:30)",
"org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.DefaultBinaryArithmeticOperation.doApply(DefaultBinaryArithmeticOperation.java:45)",
"org.elasticsearch.xpack.ql.expression.predicate.PredicateBiFunction.apply(PredicateBiFunction.java:24)",
"org.elasticsearch.xpack.ql.expression.function.scalar.whitelist.InternalQlScriptUtils.div(InternalQlScriptUtils.java:128)",
"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(InternalQlScriptUtils.div(params.v0,InternalQlScriptUtils.docValue(doc,params.v1)),params.v2))",
" ^---- HERE"
],
"script" : "InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(InternalQlScriptUtils.div(params.v0,InternalQlScriptUtils.docValue(doc,params.v1)),params.v2))",
"lang" : "painless",
"position" : {
"offset" : 119,
"start" : 0,
"end" : 156
},
"caused_by" : {
"type" : "arithmetic_exception",
"reason" : "/ by zero"
}
}
}
]
},
"status" : 400
}
I wonder if it might make sense to suppress it the same way we do in SQL, where it looks like this:
{
"error" : {
"root_cause" : [
{
"type" : "arithmetic_exception",
"reason" : "/ by zero"
}
],
"type" : "arithmetic_exception",
"reason" : "/ by zero"
},
"status" : 500
}
...n/eql/src/main/java/org/elasticsearch/xpack/eql/expression/function/EqlFunctionRegistry.java
Outdated
Show resolved
Hide resolved
...a/org/elasticsearch/xpack/ql/expression/function/scalar/whitelist/InternalQlScriptUtils.java
Outdated
Show resolved
Hide resolved
x-pack/plugin/eql/qa/common/src/main/resources/test_queries_unsupported.toml
Show resolved
Hide resolved
|
|
||
| [[queries]] | ||
| expected_event_ids = [82] | ||
| query = "file where serial_event_id % 40 == 2" |
There was a problem hiding this comment.
Can we have more complex math operations?
Few ideas:
- put the constant first and the field name second
- use the minus sign for the field as well:
file where -serial_event_id + 100 == 18 - have a more complex arithmetic set of operations:
file where serial_event_id + ((1 + 3) * 2 / (3 - 1)) * 2 == 90 OR 70 + serial_event_id < 100
There was a problem hiding this comment.
Added all of the above.
|
@imotov I like the idea for simpler response for this kind of cases. I compared with the SQL execution code, it doesn't look like it uses "painless" though, so the exception from |
astefan
left a comment
There was a problem hiding this comment.
In general LGTM. But I left few minor comments.
| expected_event_ids = [82, 83] | ||
| query = "file where serial_event_id / 2 == 41" | ||
|
|
||
| # Additional EQL queries with arithmetic operations that were not part of the original EQL implementation |
There was a problem hiding this comment.
It would be worth adding these new tests to the original EQL implementation, as well.
|
|
||
| [[queries]] | ||
| expected_event_ids = [82] | ||
| query = "file where serial_event_id + ((1 + 3) * 2 / (3 - 1)) * 2 == 90 or 70 + serial_event_id < 100" |
There was a problem hiding this comment.
I don't think this is correct.
70 + serial_event_id < 100 should match all event IDs from 1 to 29. Why is expected_event_ids only 82? Or I am missing something?
There was a problem hiding this comment.
You are absolutely right.
Looks like something changed, even the simple query like
doesn't return all 102 records:
1> [2020-04-23T19:17:13,335][INFO ][o.e.x.e.EqlActionIT ] [test] [65.test -> file where true] before test
1> [2020-04-23T19:17:13,346][INFO ][o.e.x.e.EqlActionIT ] [test] [55, 59, 60, 61, 65, 66, 67, 70, 71, 72, 75, 76, 77, 81, 82, 83, 86, 87, 88, 91, 92, 95, 96]
looking
There was a problem hiding this comment.
nevermind .... the other events have different type
There was a problem hiding this comment.
Updated to query against process type that leads to more results
| }, | ||
| // Arithmetic | ||
| new FunctionDefinition[] { | ||
| def(Add.class, Add::new,"add"), |
There was a problem hiding this comment.
Whitespace before the last parameter.
|
|
||
| [[queries]] | ||
| expected_event_ids = [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] | ||
| query = "process where serial_event_id + ((1 + 3) * 2 / (3 - 1)) * 2 == 90 or 70 + serial_event_id < 100" |
There was a problem hiding this comment.
This looks like it tests the query folding more than the integration, and folds to
process where serial_event_id + 8 == 90 or serial_event_id < 100.
Since serial_event_id of 82 is a file event, we don't have any results that match the left side.
There was a problem hiding this comment.
Yep, thanks, updated the test to match the left side of or condition.
rw-access
left a comment
There was a problem hiding this comment.
left a comment about the test_queries_supported.toml, but other than that lgtm
elastic#55137) * EQL: implement math functions: add, divide, module, multiply, subtract
Related to #54846