Browse Source

Exact math (ESQL-1507)

This turns the current math ops eval implementations to work exactly,
i.e. return null on failures caused by over-/underflows or division by
zero and corresponding Warnings.

Fix ESQL-1459
Bogdan Pintea 2 years ago
parent
commit
3c7c163923
27 changed files with 713 additions and 149 deletions
  1. 105 14
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/math.csv-spec
  2. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/AddIntsEvaluator.java
  3. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/AddLongsEvaluator.java
  4. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/AddUnsignedLongsEvaluator.java
  5. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/DivIntsEvaluator.java
  6. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/DivLongsEvaluator.java
  7. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/DivUnsignedLongsEvaluator.java
  8. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/ModIntsEvaluator.java
  9. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/ModLongsEvaluator.java
  10. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/ModUnsignedLongsEvaluator.java
  11. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/MulIntsEvaluator.java
  12. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/MulLongsEvaluator.java
  13. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/MulUnsignedLongsEvaluator.java
  14. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/SubIntsEvaluator.java
  15. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/SubLongsEvaluator.java
  16. 22 6
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/SubUnsignedLongsEvaluator.java
  17. 7 7
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Add.java
  18. 3 3
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Div.java
  19. 3 3
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Mod.java
  20. 7 7
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Mul.java
  21. 7 7
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Sub.java
  22. 20 6
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/ArithmeticMapper.java
  23. 25 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/ComparisonMapper.java
  24. 17 8
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java
  25. 12 3
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/AbstractBinaryOperatorTestCase.java
  26. 36 1
      x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/NumericUtils.java
  27. 141 0
      x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/NumericUtilsTests.java

+ 105 - 14
x-pack/plugin/esql/qa/testFixtures/src/main/resources/math.csv-spec

@@ -14,6 +14,57 @@ emp_no:integer | s:long
          10002 | 328922892
 ;
 
+addLongOverflow
+row max = 9223372036854775807 | eval sum = max + 1 | keep sum;
+
+warning:Line 1:44: evaluation of [max + 1] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: long overflow
+
+sum:long
+null
+;
+
+subLongUnderflow
+row l = -9223372036854775807 | eval sub = l - 2 | keep sub;
+
+warning:Line 1:43: evaluation of [l - 2] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: long overflow
+
+sub:long
+null
+;
+
+mulLongOverflow
+row max = 9223372036854775807 | eval mul = max * 2 | keep mul;
+
+warning:Line 1:44: evaluation of [max * 2] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: long overflow
+
+mul:long
+null
+;
+
+divLongByZero
+row max = 9223372036854775807 | eval div = max / 0 | keep div;
+
+warning:Line 1:44: evaluation of [max / 0] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: / by zero
+
+div:long
+null
+;
+
+modLongByZero
+row max = 9223372036854775807 | eval mod = max % 0 | keep mod;
+
+// ascii(%) == %25
+warning:Line 1:44: evaluation of [max %25 0] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: / by zero
+
+mod:long
+null
+;
+
 addDoubleAndDouble
 from employees | eval s = height + 5 | keep emp_no, s | sort emp_no asc | limit 2;
 
@@ -625,11 +676,14 @@ x:ul
 18446744073709551615
 ;
 
-ulAdditionPastUnsignedLongLimit
+ulAdditionOverflow
 row x = 18446744073709551615, y = to_ul(1) | eval x = x + y | keep x;
 
+warning:Line 1:55: evaluation of [x + y] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: unsigned_long overflow
+
 x:ul
-0
+null
 ;
 
 ulSubtraction
@@ -653,11 +707,14 @@ x:ul
 18446744073709551614
 ;
 
-ulSubtractionFromZero
+ulSubtractionUnderflow
 row x = to_ul(0), y = to_ul(1) | eval x = x - y | keep x;
 
+warning:Line 1:43: evaluation of [x - y] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: unsigned_long overflow
+
 x:ul
-18446744073709551615
+null
 ;
 
 ulMultiplication
@@ -667,18 +724,24 @@ x:ul
 18446744073709551614
 ;
 
-ulMultiplicationPastULMaxValue
-row x = 9223372036854775808, two = to_ul(2), three = to_ul(3) | eval times2 = x * two, times3 = x * three | keep times*;
+ulMultiplicationOverflow
+row x = 9223372036854775808, two = to_ul(2) | eval times2 = x * two | keep times2;
 
-times2:ul |times3:ul
-0         |9223372036854775808
+warning:Line 1:61: evaluation of [x * two] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: unsigned_long overflow
+
+times2:ul
+null
 ;
 
-ulMultiplicationPastULMaxValue2
+ulMultiplicationOverflow2
 row x = 9223372036854775808, y = 9223372036854775809 | eval x = x * y | keep x;
 
+warning:Line 1:65: evaluation of [x * y] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: unsigned_long overflow
+
 x:ul
-9223372036854775808
+null
 ;
 
 ulDivision
@@ -688,6 +751,16 @@ x:ul                |y:ul
 9223372036854775807 |1
 ;
 
+ulDivisionByZero
+row halfplus = 9223372036854775808, zero = to_ul(0) | eval div = halfplus / zero | keep div;
+
+warning:Line 1:66: evaluation of [halfplus / zero] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: / by zero
+
+div:ul
+null
+;
+
 ulModulo
 row max = 18446744073709551615, halfplus = 9223372036854775808, two = to_ul(2) | eval x = max % halfplus, y = halfplus % two | keep x, y;
 
@@ -695,12 +768,30 @@ x:ul                |y:ul
 9223372036854775807 |0
 ;
 
+ulModuloByZero
+row halfplus = 9223372036854775808, zero = to_ul(0) | eval mod = halfplus % zero | keep mod;
+
+// ascii(%) == %25
+warning:Line 1:66: evaluation of [halfplus %25 zero] failed, treating result as null. Only first 20 failures recorded.
+warning:java.lang.ArithmeticException: / by zero
+
+mod:ul
+null
+;
+
+
+ulMvNonSumFunctions
+row ul = [18446744073709551615, 0, 1, 9223372036854775807, 9223372036854775808] | eval mv_min(ul), mv_max(ul), mv_median(ul), mv_count(ul) | drop ul;
+
+  mv_min(ul):ul|     mv_max(ul):ul  |   mv_median(ul):ul| mv_count(ul):i
+0              |18446744073709551615|9223372036854775807|5
+;
 
-ulMvFunctions
-row ul = [18446744073709551615, 0, 1, 9223372036854775807, 9223372036854775808] | eval mv_min(ul), mv_max(ul), mv_avg(ul), mv_median(ul), mv_count(ul), mv_sum(ul) | drop ul;
+ulMvSum
+row ul = [1, 9223372036854775806, 9223372036854775808] | eval mv_sum(ul), mv_avg(ul) | drop ul;
 
-  mv_min(ul):ul|     mv_max(ul):ul  | mv_avg(ul):double   |   mv_median(ul):ul| mv_count(ul):i |     mv_sum(ul):ul
-0              |18446744073709551615|3.6893488147419105E18|9223372036854775807|5               |18446744073709551615
+     mv_sum(ul):ul  | mv_avg(ul):double
+18446744073709551615|6.148914691236517205E18
 ;
 
 ulMedianEvenCount

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/AddIntsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.IntBlock;
 import org.elasticsearch.compute.data.IntVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Add}.
  * This class is generated. Do not edit it.
  */
 public final class AddIntsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public AddIntsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public AddIntsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class AddIntsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public IntBlock eval(int positionCount, IntBlock lhsBlock, IntBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class AddIntsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendInt(Add.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendInt(Add.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public IntVector eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
-    IntVector.Builder result = IntVector.newVectorBuilder(positionCount);
+  public IntBlock eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
+    IntBlock.Builder result = IntBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendInt(Add.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      try {
+        result.appendInt(Add.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/AddLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Add}.
  * This class is generated. Do not edit it.
  */
 public final class AddLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public AddLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public AddLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class AddLongsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class AddLongsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendLong(Add.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Add.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Add.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Add.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/AddUnsignedLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Add}.
  * This class is generated. Do not edit it.
  */
 public final class AddUnsignedLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public AddUnsignedLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public AddUnsignedLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class AddUnsignedLongsEvaluator implements EvalOperator.ExpressionE
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class AddUnsignedLongsEvaluator implements EvalOperator.ExpressionE
         result.appendNull();
         continue position;
       }
-      result.appendLong(Add.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Add.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Add.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Add.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/DivIntsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.IntBlock;
 import org.elasticsearch.compute.data.IntVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Div}.
  * This class is generated. Do not edit it.
  */
 public final class DivIntsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public DivIntsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public DivIntsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class DivIntsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public IntBlock eval(int positionCount, IntBlock lhsBlock, IntBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class DivIntsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendInt(Div.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendInt(Div.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public IntVector eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
-    IntVector.Builder result = IntVector.newVectorBuilder(positionCount);
+  public IntBlock eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
+    IntBlock.Builder result = IntBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendInt(Div.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      try {
+        result.appendInt(Div.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/DivLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Div}.
  * This class is generated. Do not edit it.
  */
 public final class DivLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public DivLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public DivLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class DivLongsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class DivLongsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendLong(Div.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Div.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Div.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Div.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/DivUnsignedLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Div}.
  * This class is generated. Do not edit it.
  */
 public final class DivUnsignedLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public DivUnsignedLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public DivUnsignedLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class DivUnsignedLongsEvaluator implements EvalOperator.ExpressionE
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class DivUnsignedLongsEvaluator implements EvalOperator.ExpressionE
         result.appendNull();
         continue position;
       }
-      result.appendLong(Div.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Div.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Div.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Div.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/ModIntsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.IntBlock;
 import org.elasticsearch.compute.data.IntVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Mod}.
  * This class is generated. Do not edit it.
  */
 public final class ModIntsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public ModIntsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public ModIntsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class ModIntsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public IntBlock eval(int positionCount, IntBlock lhsBlock, IntBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class ModIntsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendInt(Mod.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendInt(Mod.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public IntVector eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
-    IntVector.Builder result = IntVector.newVectorBuilder(positionCount);
+  public IntBlock eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
+    IntBlock.Builder result = IntBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendInt(Mod.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      try {
+        result.appendInt(Mod.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/ModLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Mod}.
  * This class is generated. Do not edit it.
  */
 public final class ModLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public ModLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public ModLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class ModLongsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class ModLongsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendLong(Mod.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Mod.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Mod.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Mod.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/ModUnsignedLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Mod}.
  * This class is generated. Do not edit it.
  */
 public final class ModUnsignedLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public ModUnsignedLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public ModUnsignedLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class ModUnsignedLongsEvaluator implements EvalOperator.ExpressionE
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class ModUnsignedLongsEvaluator implements EvalOperator.ExpressionE
         result.appendNull();
         continue position;
       }
-      result.appendLong(Mod.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Mod.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Mod.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Mod.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/MulIntsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.IntBlock;
 import org.elasticsearch.compute.data.IntVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Mul}.
  * This class is generated. Do not edit it.
  */
 public final class MulIntsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public MulIntsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public MulIntsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class MulIntsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public IntBlock eval(int positionCount, IntBlock lhsBlock, IntBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class MulIntsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendInt(Mul.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendInt(Mul.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public IntVector eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
-    IntVector.Builder result = IntVector.newVectorBuilder(positionCount);
+  public IntBlock eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
+    IntBlock.Builder result = IntBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendInt(Mul.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      try {
+        result.appendInt(Mul.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/MulLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Mul}.
  * This class is generated. Do not edit it.
  */
 public final class MulLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public MulLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public MulLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class MulLongsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class MulLongsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendLong(Mul.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Mul.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Mul.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Mul.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/MulUnsignedLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Mul}.
  * This class is generated. Do not edit it.
  */
 public final class MulUnsignedLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public MulUnsignedLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public MulUnsignedLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class MulUnsignedLongsEvaluator implements EvalOperator.ExpressionE
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class MulUnsignedLongsEvaluator implements EvalOperator.ExpressionE
         result.appendNull();
         continue position;
       }
-      result.appendLong(Mul.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Mul.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Mul.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Mul.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/SubIntsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.IntBlock;
 import org.elasticsearch.compute.data.IntVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Sub}.
  * This class is generated. Do not edit it.
  */
 public final class SubIntsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public SubIntsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public SubIntsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class SubIntsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public IntBlock eval(int positionCount, IntBlock lhsBlock, IntBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class SubIntsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendInt(Sub.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendInt(Sub.processInts(lhsBlock.getInt(lhsBlock.getFirstValueIndex(p)), rhsBlock.getInt(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public IntVector eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
-    IntVector.Builder result = IntVector.newVectorBuilder(positionCount);
+  public IntBlock eval(int positionCount, IntVector lhsVector, IntVector rhsVector) {
+    IntBlock.Builder result = IntBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendInt(Sub.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      try {
+        result.appendInt(Sub.processInts(lhsVector.getInt(p), rhsVector.getInt(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/SubLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Sub}.
  * This class is generated. Do not edit it.
  */
 public final class SubLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public SubLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public SubLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class SubLongsEvaluator implements EvalOperator.ExpressionEvaluator
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class SubLongsEvaluator implements EvalOperator.ExpressionEvaluator
         result.appendNull();
         continue position;
       }
-      result.appendLong(Sub.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Sub.processLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Sub.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Sub.processLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 22 - 6
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/SubUnsignedLongsEvaluator.java

@@ -4,6 +4,7 @@
 // 2.0.
 package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
+import java.lang.ArithmeticException;
 import java.lang.Override;
 import java.lang.String;
 import org.elasticsearch.compute.data.Block;
@@ -11,18 +12,23 @@ import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.LongVector;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.Warnings;
+import org.elasticsearch.xpack.ql.tree.Source;
 
 /**
  * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Sub}.
  * This class is generated. Do not edit it.
  */
 public final class SubUnsignedLongsEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final Warnings warnings;
+
   private final EvalOperator.ExpressionEvaluator lhs;
 
   private final EvalOperator.ExpressionEvaluator rhs;
 
-  public SubUnsignedLongsEvaluator(EvalOperator.ExpressionEvaluator lhs,
+  public SubUnsignedLongsEvaluator(Source source, EvalOperator.ExpressionEvaluator lhs,
       EvalOperator.ExpressionEvaluator rhs) {
+    this.warnings = new Warnings(source);
     this.lhs = lhs;
     this.rhs = rhs;
   }
@@ -47,7 +53,7 @@ public final class SubUnsignedLongsEvaluator implements EvalOperator.ExpressionE
     if (rhsVector == null) {
       return eval(page.getPositionCount(), lhsBlock, rhsBlock);
     }
-    return eval(page.getPositionCount(), lhsVector, rhsVector).asBlock();
+    return eval(page.getPositionCount(), lhsVector, rhsVector);
   }
 
   public LongBlock eval(int positionCount, LongBlock lhsBlock, LongBlock rhsBlock) {
@@ -61,15 +67,25 @@ public final class SubUnsignedLongsEvaluator implements EvalOperator.ExpressionE
         result.appendNull();
         continue position;
       }
-      result.appendLong(Sub.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      try {
+        result.appendLong(Sub.processUnsignedLongs(lhsBlock.getLong(lhsBlock.getFirstValueIndex(p)), rhsBlock.getLong(rhsBlock.getFirstValueIndex(p))));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }
 
-  public LongVector eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
-    LongVector.Builder result = LongVector.newVectorBuilder(positionCount);
+  public LongBlock eval(int positionCount, LongVector lhsVector, LongVector rhsVector) {
+    LongBlock.Builder result = LongBlock.newBlockBuilder(positionCount);
     position: for (int p = 0; p < positionCount; p++) {
-      result.appendLong(Sub.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      try {
+        result.appendLong(Sub.processUnsignedLongs(lhsVector.getLong(p), rhsVector.getLong(p)));
+      } catch (ArithmeticException e) {
+        warnings.registerException(e);
+        result.appendNull();
+      }
     }
     return result.build();
   }

+ 7 - 7
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Add.java

@@ -9,22 +9,22 @@ package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
 import org.elasticsearch.compute.ann.Evaluator;
 
-import static org.elasticsearch.xpack.ql.util.NumericUtils.asLongUnsigned;
+import static org.elasticsearch.xpack.ql.util.NumericUtils.unsignedLongAddExact;
 
 public class Add {
-    @Evaluator(extraName = "Ints")
+    @Evaluator(extraName = "Ints", warnExceptions = { ArithmeticException.class })
     static int processInts(int lhs, int rhs) {
-        return lhs + rhs;
+        return Math.addExact(lhs, rhs);
     }
 
-    @Evaluator(extraName = "Longs")
+    @Evaluator(extraName = "Longs", warnExceptions = { ArithmeticException.class })
     static long processLongs(long lhs, long rhs) {
-        return lhs + rhs;
+        return Math.addExact(lhs, rhs);
     }
 
-    @Evaluator(extraName = "UnsignedLongs")
+    @Evaluator(extraName = "UnsignedLongs", warnExceptions = { ArithmeticException.class })
     public static long processUnsignedLongs(long lhs, long rhs) {
-        return asLongUnsigned(lhs + rhs);
+        return unsignedLongAddExact(lhs, rhs);
     }
 
     @Evaluator(extraName = "Doubles")

+ 3 - 3
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Div.java

@@ -12,17 +12,17 @@ import org.elasticsearch.compute.ann.Evaluator;
 import static org.elasticsearch.xpack.ql.util.NumericUtils.asLongUnsigned;
 
 public class Div {
-    @Evaluator(extraName = "Ints")
+    @Evaluator(extraName = "Ints", warnExceptions = { ArithmeticException.class })
     static int processInts(int lhs, int rhs) {
         return lhs / rhs;
     }
 
-    @Evaluator(extraName = "Longs")
+    @Evaluator(extraName = "Longs", warnExceptions = { ArithmeticException.class })
     static long processLongs(long lhs, long rhs) {
         return lhs / rhs;
     }
 
-    @Evaluator(extraName = "UnsignedLongs")
+    @Evaluator(extraName = "UnsignedLongs", warnExceptions = { ArithmeticException.class })
     static long processUnsignedLongs(long lhs, long rhs) {
         return asLongUnsigned(Long.divideUnsigned(asLongUnsigned(lhs), asLongUnsigned(rhs)));
     }

+ 3 - 3
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Mod.java

@@ -12,17 +12,17 @@ import org.elasticsearch.compute.ann.Evaluator;
 import static org.elasticsearch.xpack.ql.util.NumericUtils.asLongUnsigned;
 
 public class Mod {
-    @Evaluator(extraName = "Ints")
+    @Evaluator(extraName = "Ints", warnExceptions = { ArithmeticException.class })
     static int processInts(int lhs, int rhs) {
         return lhs % rhs;
     }
 
-    @Evaluator(extraName = "Longs")
+    @Evaluator(extraName = "Longs", warnExceptions = { ArithmeticException.class })
     static long processLongs(long lhs, long rhs) {
         return lhs % rhs;
     }
 
-    @Evaluator(extraName = "UnsignedLongs")
+    @Evaluator(extraName = "UnsignedLongs", warnExceptions = { ArithmeticException.class })
     static long processUnsignedLongs(long lhs, long rhs) {
         return asLongUnsigned(Long.remainderUnsigned(asLongUnsigned(lhs), asLongUnsigned(rhs)));
     }

+ 7 - 7
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Mul.java

@@ -9,22 +9,22 @@ package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
 import org.elasticsearch.compute.ann.Evaluator;
 
-import static org.elasticsearch.xpack.ql.util.NumericUtils.asLongUnsigned;
+import static org.elasticsearch.xpack.ql.util.NumericUtils.unsignedLongMultiplyExact;
 
 public class Mul {
-    @Evaluator(extraName = "Ints")
+    @Evaluator(extraName = "Ints", warnExceptions = { ArithmeticException.class })
     static int processInts(int lhs, int rhs) {
-        return lhs * rhs;
+        return Math.multiplyExact(lhs, rhs);
     }
 
-    @Evaluator(extraName = "Longs")
+    @Evaluator(extraName = "Longs", warnExceptions = { ArithmeticException.class })
     static long processLongs(long lhs, long rhs) {
-        return lhs * rhs;
+        return Math.multiplyExact(lhs, rhs);
     }
 
-    @Evaluator(extraName = "UnsignedLongs")
+    @Evaluator(extraName = "UnsignedLongs", warnExceptions = { ArithmeticException.class })
     static long processUnsignedLongs(long lhs, long rhs) {
-        return asLongUnsigned(asLongUnsigned(lhs) * asLongUnsigned(rhs));
+        return unsignedLongMultiplyExact(lhs, rhs);
     }
 
     @Evaluator(extraName = "Doubles")

+ 7 - 7
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Sub.java

@@ -9,22 +9,22 @@ package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;
 
 import org.elasticsearch.compute.ann.Evaluator;
 
-import static org.elasticsearch.xpack.ql.util.NumericUtils.asLongUnsigned;
+import static org.elasticsearch.xpack.ql.util.NumericUtils.unsignedLongSubtractExact;
 
 public class Sub {
-    @Evaluator(extraName = "Ints")
+    @Evaluator(extraName = "Ints", warnExceptions = { ArithmeticException.class })
     static int processInts(int lhs, int rhs) {
-        return lhs - rhs;
+        return Math.subtractExact(lhs, rhs);
     }
 
-    @Evaluator(extraName = "Longs")
+    @Evaluator(extraName = "Longs", warnExceptions = { ArithmeticException.class })
     static long processLongs(long lhs, long rhs) {
-        return lhs - rhs;
+        return Math.subtractExact(lhs, rhs);
     }
 
-    @Evaluator(extraName = "UnsignedLongs")
+    @Evaluator(extraName = "UnsignedLongs", warnExceptions = { ArithmeticException.class })
     static long processUnsignedLongs(long lhs, long rhs) {
-        return asLongUnsigned(lhs - rhs);
+        return unsignedLongSubtractExact(lhs, rhs);
     }
 
     @Evaluator(extraName = "Doubles")

+ 20 - 6
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/ArithmeticMapper.java

@@ -7,6 +7,7 @@
 
 package org.elasticsearch.xpack.esql.planner;
 
+import org.elasticsearch.common.TriFunction;
 import org.elasticsearch.compute.operator.EvalOperator;
 import org.elasticsearch.xpack.esql.type.EsqlDataTypeRegistry;
 import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Add;
@@ -15,6 +16,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Div;
 import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mod;
 import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mul;
 import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Sub;
+import org.elasticsearch.xpack.ql.tree.Source;
 import org.elasticsearch.xpack.ql.type.DataType;
 import org.elasticsearch.xpack.ql.type.DataTypes;
 
@@ -64,15 +66,27 @@ abstract class ArithmeticMapper<T extends ArithmeticOperation> extends EvalMappe
     ) {
     };
 
-    private final BiFunction<EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> ints;
-    private final BiFunction<EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> longs;
-    private final BiFunction<EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> ulongs;
+    private final TriFunction<
+        Source,
+        EvalOperator.ExpressionEvaluator,
+        EvalOperator.ExpressionEvaluator,
+        EvalOperator.ExpressionEvaluator> ints;
+    private final TriFunction<
+        Source,
+        EvalOperator.ExpressionEvaluator,
+        EvalOperator.ExpressionEvaluator,
+        EvalOperator.ExpressionEvaluator> longs;
+    private final TriFunction<
+        Source,
+        EvalOperator.ExpressionEvaluator,
+        EvalOperator.ExpressionEvaluator,
+        EvalOperator.ExpressionEvaluator> ulongs;
     private final BiFunction<EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> doubles;
 
     private ArithmeticMapper(
-        BiFunction<EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> ints,
-        BiFunction<EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> longs,
-        BiFunction<EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> ulongs,
+        TriFunction<Source, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> ints,
+        TriFunction<Source, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> longs,
+        TriFunction<Source, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> ulongs,
         BiFunction<EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator, EvalOperator.ExpressionEvaluator> doubles
     ) {
         this.ints = ints;

+ 25 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/ComparisonMapper.java

@@ -7,6 +7,7 @@
 
 package org.elasticsearch.xpack.esql.planner;
 
+import org.elasticsearch.common.TriFunction;
 import org.elasticsearch.compute.operator.EvalOperator;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cast;
 import org.elasticsearch.xpack.esql.type.EsqlDataTypeRegistry;
@@ -18,6 +19,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Great
 import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan;
 import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual;
 import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals;
+import org.elasticsearch.xpack.ql.tree.Source;
 import org.elasticsearch.xpack.ql.type.DataType;
 import org.elasticsearch.xpack.ql.type.DataTypes;
 
@@ -159,4 +161,27 @@ abstract class ComparisonMapper<T extends BinaryComparison> extends EvalMapper.E
         );
         return () -> buildEvaluator.apply(lhs.get(), rhs.get());
     }
+
+    static Supplier<EvalOperator.ExpressionEvaluator> castToEvaluator(
+        BinaryOperator<?, ?, ?, ?> op,
+        Layout layout,
+        DataType required,
+        TriFunction<
+            Source,
+            EvalOperator.ExpressionEvaluator,
+            EvalOperator.ExpressionEvaluator,
+            EvalOperator.ExpressionEvaluator> buildEvaluator
+    ) {
+        Supplier<EvalOperator.ExpressionEvaluator> lhs = Cast.cast(
+            op.left().dataType(),
+            required,
+            EvalMapper.toEvaluator(op.left(), layout)
+        );
+        Supplier<EvalOperator.ExpressionEvaluator> rhs = Cast.cast(
+            op.right().dataType(),
+            required,
+            EvalMapper.toEvaluator(op.right(), layout)
+        );
+        return () -> buildEvaluator.apply(op.source(), lhs.get(), rhs.get());
+    }
 }

+ 17 - 8
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java

@@ -22,6 +22,7 @@ import java.util.List;
 
 import static java.util.Collections.singletonList;
 import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
+import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.nullValue;
 
@@ -91,14 +92,18 @@ public abstract class AbstractMultivalueFunctionTestCase extends AbstractScalarF
                     () -> type == DataTypes.NULL || (insertNulls && rarely()) ? singletonList(null) : List.of(dataForPosition(type))
                 );
                 Expression expression = build(Source.EMPTY, field("f", type));
-                Block result = evaluator(expression).get().eval(new Page(BlockUtils.fromList(data)));
-                for (int p = 0; p < data.size(); p++) {
-                    if (data.get(p).get(0) == null) {
-                        assertTrue(type.toString(), result.isNull(p));
-                    } else {
-                        assertFalse(type.toString(), result.isNull(p));
-                        assertThat(type.toString(), toJavaObject(result, p), resultMatcherForInput((List<?>) data.get(p).get(0), type));
+                try {
+                    Block result = evaluator(expression).get().eval(new Page(BlockUtils.fromList(data)));
+                    for (int p = 0; p < data.size(); p++) {
+                        if (data.get(p).get(0) == null) {
+                            assertTrue(type.toString(), result.isNull(p));
+                        } else {
+                            assertFalse(type.toString(), result.isNull(p));
+                            assertThat(type.toString(), toJavaObject(result, p), resultMatcherForInput((List<?>) data.get(p).get(0), type));
+                        }
                     }
+                } catch (ArithmeticException ae) {
+                    assertThat(ae.getMessage(), equalTo(type.typeName() + " overflow"));
                 }
             }
         }
@@ -118,7 +123,11 @@ public abstract class AbstractMultivalueFunctionTestCase extends AbstractScalarF
             List<Object> data = type == DataTypes.NULL ? null : randomList(1, 100, () -> randomLiteral(type).value());
             Expression expression = build(Source.EMPTY, new Literal(Source.EMPTY, data, type));
             assertTrue(expression.foldable());
-            assertThat(expression.fold(), resultMatcherForInput(data, type));
+            try {
+                assertThat(expression.fold(), resultMatcherForInput(data, type));
+            } catch (ArithmeticException ae) {
+                assertThat(ae.getMessage(), equalTo(type.typeName() + " overflow"));
+            }
         }
     }
 

+ 12 - 3
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/AbstractBinaryOperatorTestCase.java

@@ -24,6 +24,7 @@ import java.util.List;
 import java.util.Locale;
 
 import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
+import static org.elasticsearch.xpack.ql.type.DataTypeConverter.commonType;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.nullValue;
@@ -83,9 +84,17 @@ public abstract class AbstractBinaryOperatorTestCase extends AbstractFunctionTes
                     field("rhs", rhsType)
                 );
                 Object result = toJavaObject(evaluator(op).get().eval(row(List.of(lhs.value(), rhs.value()))), 0);
-                // The type's currently only used for distinguishing between LONG and UNSIGNED_LONG. UL requires both operands be of the
-                // same type, so either left or right type can be provided below. But otherwise the common type can be used instead.
-                assertThat(op.toString(), result, resultMatcher(List.of(lhs.value(), rhs.value()), lhsType));
+                if (result == null) {
+                    assertCriticalWarnings(
+                        "Line -1:-1: evaluation of [" + op + "] failed, treating result as null. Only first 20 failures recorded.",
+                        "java.lang.ArithmeticException: " + commonType(lhsType, rhsType).typeName() + " overflow"
+                    );
+                } else {
+                    // The type's currently only used for distinguishing between LONG and UNSIGNED_LONG. UL requires both operands be of
+                    // the same type, so either left or right type can be provided below. But otherwise the common type can be used
+                    // instead.
+                    assertThat(op.toString(), result, resultMatcher(List.of(lhs.value(), rhs.value()), lhsType));
+                }
             }
         }
     }

+ 36 - 1
x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/NumericUtils.java

@@ -25,6 +25,8 @@ public abstract class NumericUtils {
     public static final long ONE_AS_UNSIGNED_LONG = asLongUnsigned(BigInteger.ONE);
     public static final long ZERO_AS_UNSIGNED_LONG = asLongUnsigned(BigInteger.ZERO);
 
+    private static final String UNSIGNED_LONG_OVERFLOW = "unsigned_long overflow";
+
     public static boolean isUnsignedLong(BigInteger bi) {
         return bi.signum() >= 0 && bi.compareTo(UNSIGNED_LONG_MAX) <= 0;
     }
@@ -39,7 +41,7 @@ public abstract class NumericUtils {
 
     public static BigInteger asUnsignedLong(BigInteger bi) {
         if (isUnsignedLong(bi) == false) {
-            throw new ArithmeticException("unsigned_long overflow");
+            throw new ArithmeticException(UNSIGNED_LONG_OVERFLOW);
         }
         return bi;
     }
@@ -94,6 +96,39 @@ public abstract class NumericUtils {
         return l < 0 ? twosComplement(l) : LONG_MAX_PLUS_ONE_AS_DOUBLE + l;
     }
 
+    public static long unsignedLongAddExact(long x, long y) {
+        long s;
+        if (
+        // both operands are positive, so the UL equivalents are >= Long.MAX_VALUE + 1, so sum will be above UNSIGNED_LONG_MAX
+        (x | y) >= 0
+            // if operands have opposing signs, the UL corresponding to the positive one is >= Long.MAX_VALUE + 1 and
+            // the UL corresponding to the negative one between [0, Long.MAX_VALUE] ==> non-negative sum means value wrap, i.e. overflow
+            || ((s = (x + y)) >= 0 && (x ^ y) < 0)) {
+            throw new ArithmeticException(UNSIGNED_LONG_OVERFLOW);
+        }
+        return asLongUnsigned(s);
+    }
+
+    public static long unsignedLongSubtractExact(long x, long y) {
+        if (x < y) { // UL keeps the ordering after shifting to fit into long range
+            throw new ArithmeticException(UNSIGNED_LONG_OVERFLOW);
+        }
+        return asLongUnsigned(x - y);
+    }
+
+    public static long unsignedLongMultiplyExact(long x, long y) {
+        long ux = asLongUnsigned(x);
+        long uy = asLongUnsigned(y);
+        if (unsignedLongMultiplyHigh(ux, uy) != 0) { // TODO: replace with Math#unsignedMultiplyHigh() in JDK 18 when available
+            throw new ArithmeticException(UNSIGNED_LONG_OVERFLOW);
+        }
+        return asLongUnsigned(ux * uy);
+    }
+
+    public static long unsignedLongMultiplyHigh(long x, long y) {
+        return Math.multiplyHigh(x, y) + (y & (x >> 63)) + (x & (y >> 63));
+    }
+
     private static long twosComplement(long l) {
         return l ^ TWOS_COMPLEMENT_BITMASK;
     }

+ 141 - 0
x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/NumericUtilsTests.java

@@ -0,0 +1,141 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.ql.util;
+
+import org.elasticsearch.test.ESTestCase;
+
+import java.math.BigInteger;
+import java.util.function.BiFunction;
+
+import static org.elasticsearch.xpack.ql.util.NumericUtils.asLongUnsigned;
+import static org.elasticsearch.xpack.ql.util.NumericUtils.unsignedLongAsNumber;
+import static org.elasticsearch.xpack.ql.util.StringUtils.parseIntegral;
+import static org.hamcrest.Matchers.equalTo;
+
+public class NumericUtilsTests extends ESTestCase {
+
+    public void testUnsignedLongAddExact() {
+        assertThat(addExact("9223372036854775808", "0"), equalTo("9223372036854775808"));
+        assertThat(addExact("9223372036854775807", "0"), equalTo("9223372036854775807"));
+        assertThat(addExact("9223372036854775808", "1"), equalTo("9223372036854775809"));
+        assertThat(addExact("9223372036854775807", "1"), equalTo("9223372036854775808"));
+
+        assertThat(addExact("0", "0"), equalTo("0"));
+        assertThat(addExact("1", "1"), equalTo("2"));
+
+        assertThat(addExact("9223372036854775808", "9223372036854775807"), equalTo("18446744073709551615"));
+        assertThat(addExact("9223372036854775807", "9223372036854775807"), equalTo("18446744073709551614"));
+        assertThat(addExact("9223372036854775806", "9223372036854775807"), equalTo("18446744073709551613"));
+        assertThat(addExact("9223372036854775805", "9223372036854775807"), equalTo("18446744073709551612"));
+
+        assertThat(addExact("18446744073709551612", "3"), equalTo("18446744073709551615"));
+        assertThat(addExact("18446744073709551613", "2"), equalTo("18446744073709551615"));
+        assertThat(addExact("18446744073709551614", "1"), equalTo("18446744073709551615"));
+        assertThat(addExact("18446744073709551615", "0"), equalTo("18446744073709551615"));
+
+        expectThrows(ArithmeticException.class, () -> addExact("18446744073709551615", "1"));
+        expectThrows(ArithmeticException.class, () -> addExact("18446744073709551615", "2"));
+        expectThrows(ArithmeticException.class, () -> addExact("18446744073709551615", "3"));
+        expectThrows(ArithmeticException.class, () -> addExact("18446744073709551614", "2"));
+        expectThrows(ArithmeticException.class, () -> addExact("18446744073709551615", "18446744073709551615"));
+        expectThrows(ArithmeticException.class, () -> addExact("18446744073709551615", "18446744073709551614"));
+        expectThrows(ArithmeticException.class, () -> addExact("18446744073709551615", "9223372036854775808"));
+        expectThrows(ArithmeticException.class, () -> addExact("18446744073709551615", "9223372036854775807"));
+        expectThrows(ArithmeticException.class, () -> addExact("9223372036854775808", "9223372036854775808"));
+        expectThrows(ArithmeticException.class, () -> addExact("9223372036854775807", "9223372036854775809"));
+    }
+
+    public void testUnsignedLongSubtractExact() {
+        assertThat(subExact("18446744073709551615", "0"), equalTo("18446744073709551615"));
+        assertThat(subExact("18446744073709551615", "18446744073709551615"), equalTo("0"));
+
+        assertThat(subExact("18446744073709551615", "9223372036854775808"), equalTo("9223372036854775807"));
+        assertThat(subExact("18446744073709551615", "9223372036854775807"), equalTo("9223372036854775808"));
+        assertThat(subExact("18446744073709551615", "9223372036854775806"), equalTo("9223372036854775809"));
+        assertThat(subExact("18446744073709551614", "9223372036854775808"), equalTo("9223372036854775806"));
+        assertThat(subExact("18446744073709551614", "9223372036854775807"), equalTo("9223372036854775807"));
+
+        assertThat(subExact("9223372036854775809", "9223372036854775809"), equalTo("0"));
+        assertThat(subExact("9223372036854775808", "9223372036854775808"), equalTo("0"));
+
+        assertThat(subExact("9223372036854775808", "1"), equalTo("9223372036854775807"));
+        assertThat(subExact("9223372036854775807", "1"), equalTo("9223372036854775806"));
+        assertThat(subExact("9223372036854775808", "0"), equalTo("9223372036854775808"));
+        assertThat(subExact("9223372036854775807", "0"), equalTo("9223372036854775807"));
+
+        assertThat(subExact("0", "0"), equalTo("0"));
+        assertThat(subExact("1", "1"), equalTo("0"));
+
+        expectThrows(ArithmeticException.class, () -> subExact("9223372036854775807", "9223372036854775808"));
+        expectThrows(ArithmeticException.class, () -> subExact("9223372036854775805", "9223372036854775808"));
+        expectThrows(ArithmeticException.class, () -> subExact("9223372036854775805", "9223372036854775806"));
+        expectThrows(ArithmeticException.class, () -> subExact("0", "9223372036854775808"));
+        expectThrows(ArithmeticException.class, () -> subExact("0", "9223372036854775807"));
+        expectThrows(ArithmeticException.class, () -> subExact("0", "9223372036854775805"));
+    }
+
+    // 18446744073709551615 = 3 * 5 * 17 * 257 * 641 * 65537 * 6700417
+    public void testUnsignedLongMultiplyExact() {
+        assertThat(mulExact("6148914691236517205", "3"), equalTo("18446744073709551615"));
+        expectThrows(ArithmeticException.class, () -> mulExact("6148914691236517205", "4"));
+        expectThrows(ArithmeticException.class, () -> mulExact("6148914691236517206", "3"));
+
+        assertThat(mulExact("3689348814741910323", "5"), equalTo("18446744073709551615"));
+        expectThrows(ArithmeticException.class, () -> mulExact("3689348814741910324", "5"));
+        expectThrows(ArithmeticException.class, () -> mulExact("3689348814741910323", "6"));
+
+        assertThat(mulExact("6700417", "2753074036095"), equalTo("18446744073709551615"));
+        expectThrows(ArithmeticException.class, () -> mulExact("6700418", "2753074036095"));
+        expectThrows(ArithmeticException.class, () -> mulExact("6700417", "2753074036096"));
+
+        assertThat(mulExact("1844674407370955161", "0"), equalTo("0"));
+        assertThat(mulExact("1844674407370955161", "9"), equalTo("16602069666338596449"));
+        assertThat(mulExact("1844674407370955161", "10"), equalTo("18446744073709551610"));
+        expectThrows(ArithmeticException.class, () -> mulExact("1844674407370955161", "11"));
+
+        assertThat(mulExact("18446744073709551615", "1"), equalTo("18446744073709551615"));
+        expectThrows(ArithmeticException.class, () -> mulExact("18446744073709551615", "2"));
+        expectThrows(ArithmeticException.class, () -> mulExact("18446744073709551615", "10"));
+        expectThrows(ArithmeticException.class, () -> mulExact("18446744073709551615", "18446744073709551615"));
+
+        assertThat(mulExact("9223372036854775807", "2"), equalTo("18446744073709551614"));
+        expectThrows(ArithmeticException.class, () -> mulExact("9223372036854775808", "2"));
+        expectThrows(ArithmeticException.class, () -> mulExact("9223372036854775807", "3"));
+        expectThrows(ArithmeticException.class, () -> mulExact("9223372036854775808", "9223372036854775808"));
+        expectThrows(ArithmeticException.class, () -> mulExact("9223372036854775807", "9223372036854775807"));
+        expectThrows(ArithmeticException.class, () -> mulExact("9223372036854775807", "9223372036854775808"));
+
+        assertThat(mulExact("1", "1"), equalTo("1"));
+        assertThat(mulExact("0", "1"), equalTo("0"));
+        assertThat(mulExact("0", "0"), equalTo("0"));
+    }
+
+    private static String addExact(String x, String y) {
+        return exactOperation(x, y, NumericUtils::unsignedLongAddExact);
+    }
+
+    private static String subExact(String x, String y) {
+        return exactOperation(x, y, NumericUtils::unsignedLongSubtractExact);
+    }
+
+    private static String mulExact(String x, String y) {
+        return exactOperation(x, y, NumericUtils::unsignedLongMultiplyExact);
+    }
+
+    private static String exactOperation(String x, String y, BiFunction<Long, Long, Long> operation) {
+        long xl = parseUnsignedLong(x);
+        long yl = parseUnsignedLong(y);
+        long rl = operation.apply(xl, yl);
+        return unsignedLongAsNumber(rl).toString();
+    }
+
+    private static long parseUnsignedLong(String number) {
+        Number n = parseIntegral(number);
+        return n instanceof BigInteger bi ? asLongUnsigned(bi) : asLongUnsigned(n.longValue());
+    }
+}