99
1010import org .elasticsearch .xpack .esql .core .expression .predicate .operator .arithmetic .Arithmetics ;
1111import org .elasticsearch .xpack .esql .core .tree .Source ;
12+ import org .elasticsearch .xpack .esql .expression .promql .predicate .operator .arithmetic .VectorBinaryArithmetic .ArithmeticOp ;
13+ import org .elasticsearch .xpack .esql .expression .promql .predicate .operator .comparison .VectorBinaryComparison .ComparisonOp ;
1214import org .elasticsearch .xpack .esql .parser .ParsingException ;
1315
1416import java .time .Duration ;
2022 * - Durations and numbers (converts to seconds, computes, converts back)
2123 * - Durations and durations (only for ADD/SUB)
2224 */
23- public class PromqlArithmeticUtils {
25+ public class PromqlFoldingUtils {
2426
2527 /**
2628 * Evaluate arithmetic operation between two scalar values at parse time.
@@ -31,7 +33,7 @@ public class PromqlArithmeticUtils {
3133 * @param operation The arithmetic operation
3234 * @return Result value (Number or Duration)
3335 */
34- public static Object evaluate (Source source , Object left , Object right , ArithmeticOperation operation ) {
36+ public static Object evaluate (Source source , Object left , Object right , ArithmeticOp operation ) {
3537 // Dispatch to appropriate handler based on operand types
3638 if (left instanceof Duration leftDuration ) {
3739 if (right instanceof Duration rightDuration ) {
@@ -58,14 +60,14 @@ public static Object evaluate(Source source, Object left, Object right, Arithmet
5860 /**
5961 * Duration op Duration (only ADD and SUB supported).
6062 */
61- private static Duration arithmetics (Source source , Duration left , Duration right , ArithmeticOperation op ) {
63+ private static Duration arithmetics (Source source , Duration left , Duration right , ArithmeticOp op ) {
6264 Duration result = switch (op ) {
6365 case ADD -> left .plus (right );
6466 case SUB -> left .minus (right );
6567 default -> throw new ParsingException (
6668 source ,
6769 "Operation [{}] not supported between two durations" ,
68- op . symbol ()
70+ op
6971 );
7072 };
7173
@@ -77,7 +79,7 @@ private static Duration arithmetics(Source source, Duration left, Duration right
7779 * For ADD/SUB: Number interpreted as seconds (PromQL convention).
7880 * For MUL/DIV/MOD/POW: Number is a dimensionless scalar.
7981 */
80- private static Duration arithmetics (Source source , Duration duration , Number scalar , ArithmeticOperation op ) {
82+ private static Duration arithmetics (Source source , Duration duration , Number scalar , ArithmeticOp op ) {
8183 long durationSeconds = duration .getSeconds ();
8284 long scalarValue = scalar .longValue ();
8385
@@ -113,15 +115,15 @@ private static Duration arithmetics(Source source, Duration duration, Number sca
113115 return Duration .ofSeconds (resultSeconds );
114116 }
115117
116- private static Duration arithmetics (Source source , Number scalar , Duration duration , ArithmeticOperation op ) {
118+ private static Duration arithmetics (Source source , Number scalar , Duration duration , ArithmeticOp op ) {
117119 return switch (op ) {
118- case ADD -> arithmetics (source , duration , scalar , ArithmeticOperation .ADD );
119- case SUB -> arithmetics (source , Duration .ofSeconds (scalar .longValue ()), duration , ArithmeticOperation .SUB );
120- case MUL -> arithmetics (source , duration , scalar , ArithmeticOperation .MUL );
120+ case ADD -> arithmetics (source , duration , scalar , ArithmeticOp .ADD );
121+ case SUB -> arithmetics (source , Duration .ofSeconds (scalar .longValue ()), duration , ArithmeticOp .SUB );
122+ case MUL -> arithmetics (source , duration , scalar , ArithmeticOp .MUL );
121123 default -> throw new ParsingException (
122124 source ,
123125 "Operation [{}] not supported with scalar on left and duration on right" ,
124- op . symbol ()
126+ op
125127 );
126128 };
127129 }
@@ -130,7 +132,7 @@ private static Duration arithmetics(Source source, Number scalar, Duration durat
130132 * Number op Number (pure numeric operations).
131133 * Delegates to Arithmetics for consistent numeric handling.
132134 */
133- private static Number numericArithmetics (Source source , Number left , Number right , ArithmeticOperation op ) {
135+ private static Number numericArithmetics (Source source , Number left , Number right , ArithmeticOp op ) {
134136 try {
135137 return switch (op ) {
136138 case ADD -> Arithmetics .add (left , right );
@@ -158,6 +160,37 @@ private static Number numericArithmetics(Source source, Number left, Number righ
158160 }
159161 }
160162
163+ /**
164+ * Evaluate comparison operation between two numbers at parse time.
165+ *
166+ * @param left Left operand (Number)
167+ * @param right Right operand (Number)
168+ * @param operation The comparison operation
169+ * @return true if comparison holds, false otherwise
170+ */
171+ public static boolean evaluate (Source source , Object left , Object right , ComparisonOp operation ) {
172+ if (left instanceof Number ln && right instanceof Number rn ) {
173+ // Get double values once, reuse for comparison - avoids extra allocation
174+ double l = ln .doubleValue ();
175+ double r = rn .doubleValue ();
176+
177+ return switch (operation ) {
178+ case EQ -> l == r ;
179+ case NEQ -> l != r ;
180+ case GT -> l > r ;
181+ case GTE -> l >= r ;
182+ case LT -> l < r ;
183+ case LTE -> l <= r ;
184+ };
185+ }
186+ throw new ParsingException (
187+ source ,
188+ "Cannot perform comparison between [{}] and [{}]" ,
189+ left .getClass ().getSimpleName (),
190+ right .getClass ().getSimpleName ()
191+ );
192+ }
193+
161194 /**
162195 * Validate that duration is positive (PromQL requirement).
163196 */
0 commit comments