Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2125697
Remove folding from Percentile
julian-elastic Jul 24, 2025
d019b65
Remove folding from CountDistinct
julian-elastic Jul 24, 2025
140af7e
Remove folding from MvSort
julian-elastic Jul 24, 2025
588a388
Remove folding from AggregateFunction and CIDRMatch
julian-elastic Jul 24, 2025
cddf15a
bugfixes, add support for IN and CIDRMatch
julian-elastic Jul 24, 2025
1b46d3c
Add support for more functions
julian-elastic Jul 24, 2025
5fa1b5b
Bugfix
julian-elastic Jul 24, 2025
82c88ef
Merge branch 'main' into foldable_part2_v2
julian-elastic Jul 29, 2025
c4f70d6
Address code review comments
julian-elastic Jul 30, 2025
bb86fbb
Update docs/changelog/131870.yaml
julian-elastic Jul 30, 2025
607af02
Merge branch 'main' into foldable_part2_v2
julian-elastic Jul 30, 2025
dcf143b
Merge branch 'main' into foldable_part2_v2
julian-elastic Jul 30, 2025
f89baab
Merge branch 'main' into foldable_part2_v2
julian-elastic Jul 31, 2025
845db85
Delete docs/changelog/131870.yaml
julian-elastic Jul 31, 2025
88edfdf
Merge branch 'main' into foldable_part2_v2
julian-elastic Aug 1, 2025
15439de
Refactoring - Remove FunctionUtils.java and move all functionality to…
julian-elastic Aug 1, 2025
fbfb4ce
Fix MvSort checks
julian-elastic Aug 1, 2025
98cbca7
Merge branch 'main' into foldable_part2_v2
julian-elastic Aug 13, 2025
7761e3f
Fix merge error
julian-elastic Aug 13, 2025
c063010
Address code review comments
julian-elastic Aug 13, 2025
a6e1f91
Address more code review comments
julian-elastic Aug 13, 2025
58b31ed
Merge branch 'main' into foldable_part2_v2
julian-elastic Aug 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,18 @@ public static Object valueOf(FoldContext ctx, Expression e) {
}
throw new QlIllegalArgumentException("Cannot determine value for {}", e);
}

public static Object literalValueOf(Expression e) {
if (e instanceof Literal literal) {
return literal.value();
}
throw new QlIllegalArgumentException("Expected literal, but got {}", e);
}

public static Object extractLiteralOrReturnSelf(Expression e) {
if (e instanceof Literal literal) {
return literal.value();
}
return e;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.elasticsearch.xpack.esql.capabilities.PostAnalysisPlanVerificationAware;
import org.elasticsearch.xpack.esql.common.Failures;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
import org.elasticsearch.xpack.esql.core.expression.Literal;
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
import org.elasticsearch.xpack.esql.core.expression.function.Function;
Expand Down Expand Up @@ -95,7 +94,7 @@ public List<? extends Expression> parameters() {

public boolean hasFilter() {
return filter != null
&& (filter.foldable() == false || Boolean.TRUE.equals(filter.fold(FoldContext.small() /* TODO remove me */)) == false);
&& (filter.foldable() == false || (filter instanceof Literal literal && Boolean.TRUE.equals(literal.value()) == false));
}

public Expression filter() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import org.elasticsearch.compute.aggregation.CountDistinctLongAggregatorFunctionSupplier;
import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
import org.elasticsearch.xpack.esql.core.expression.Literal;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source;
Expand All @@ -43,6 +42,7 @@
import java.util.Map;
import java.util.function.Function;

import static org.elasticsearch.core.Strings.format;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isFoldable;
Expand Down Expand Up @@ -210,16 +210,23 @@ protected TypeResolution resolveType() {
@Override
public AggregatorFunctionSupplier supplier() {
DataType type = field().dataType();
int precision = this.precision == null
? DEFAULT_PRECISION
: ((Number) this.precision.fold(FoldContext.small() /* TODO remove me */)).intValue();
int precision = this.precision == null ? DEFAULT_PRECISION : precisionValue();
if (SUPPLIERS.containsKey(type) == false) {
// If the type checking did its job, this should never happen
throw EsqlIllegalArgumentException.illegalDataType(type);
}
return SUPPLIERS.get(type).apply(precision);
}

private int precisionValue() {
if (precision instanceof Literal literal) {
return ((Number) literal.value()).intValue();
}
throw new EsqlIllegalArgumentException(
format(null, "Precision value must be a constant integer in [{}], found [{}]", source(), precision)
);
}

@Override
public Expression surrogate() {
var s = source();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
import org.elasticsearch.compute.aggregation.PercentileDoubleAggregatorFunctionSupplier;
import org.elasticsearch.compute.aggregation.PercentileIntAggregatorFunctionSupplier;
import org.elasticsearch.compute.aggregation.PercentileLongAggregatorFunctionSupplier;
import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
import org.elasticsearch.xpack.esql.core.expression.Literal;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source;
Expand All @@ -34,6 +34,7 @@
import java.util.List;

import static java.util.Collections.singletonList;
import static org.elasticsearch.core.Strings.format;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isFoldable;
Expand Down Expand Up @@ -169,7 +170,12 @@ protected AggregatorFunctionSupplier doubleSupplier() {
}

private int percentileValue() {
return ((Number) percentile.fold(FoldContext.small() /* TODO remove me */)).intValue();
if (percentile() instanceof Literal literal) {
return ((Number) literal.value()).intValue();
}
throw new EsqlIllegalArgumentException(
format(null, "Percentile value must be a constant integer in [{}], found [{}]", source(), percentile)
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.elasticsearch.xpack.esql.capabilities.TranslationAware;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.Expressions;
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
import org.elasticsearch.xpack.esql.core.expression.Foldables;
import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
import org.elasticsearch.xpack.esql.core.querydsl.query.TermsQuery;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
Expand Down Expand Up @@ -189,7 +189,7 @@ public Query asQuery(LucenePushdownPredicates pushdownPredicates, TranslatorHand
Check.isTrue(Expressions.foldable(matches), "Expected foldable matches, but got [{}]", matches);

String targetFieldName = handler.nameOf(fa.exactAttribute());
Set<Object> set = new LinkedHashSet<>(Expressions.fold(FoldContext.small() /* TODO remove me */, matches));
Set<Object> set = new LinkedHashSet<>(matches.stream().map(Foldables::extractLiteralOrReturnSelf).toList());

return new TermsQuery(source(), targetFieldName, set);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@
import org.elasticsearch.xpack.esql.planner.PlannerUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND;
Expand Down Expand Up @@ -146,6 +148,19 @@ public boolean foldable() {
return field.foldable() && (order == null || order.foldable());
}

@Override
public Object fold(FoldContext ctx) {
if (order != null && order instanceof Literal == false) {
// if we are here, we know that order is foldable, so we can safely fold it
Literal newOrder = Literal.of(ctx, order);
List<Expression> newChildren = new ArrayList<>();
newChildren.add(field);
newChildren.add(newOrder);
return replaceChildren(newChildren).fold(ctx);
}
return super.fold(ctx);
}

@Override
public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) {
boolean ordering = true;
Expand Down Expand Up @@ -246,7 +261,7 @@ public void postOptimizationVerification(Failures failures) {
sourceText(),
BytesRefs.toString(ASC.value()),
BytesRefs.toString(DESC.value()),
BytesRefs.toString(order.fold(FoldContext.small() /* TODO remove me */))
BytesRefs.toString(order)
)
);
}
Expand All @@ -255,16 +270,21 @@ public void postOptimizationVerification(Failures failures) {
private boolean isValidOrder() {
boolean isValidOrder = true;
if (order != null && order.foldable()) {
Object obj = order.fold(FoldContext.small() /* TODO remove me */);
String o = null;
if (obj instanceof BytesRef ob) {
o = ob.utf8ToString();
} else if (obj instanceof String os) {
o = os;
}
if (o == null
|| o.equalsIgnoreCase(BytesRefs.toString(ASC.value())) == false
&& o.equalsIgnoreCase(BytesRefs.toString(DESC.value())) == false) {
if (order instanceof Literal literal) {
Object obj = literal.value();
String o = null;
if (obj instanceof BytesRef ob) {
o = ob.utf8ToString();
} else if (obj instanceof String os) {
o = os;
}
if (o == null
|| o.equalsIgnoreCase(BytesRefs.toString(ASC.value())) == false
&& o.equalsIgnoreCase(BytesRefs.toString(DESC.value())) == false) {
isValidOrder = false;
}
} else {
// order should be folded already, so if it is not literal it is invalid
isValidOrder = false;
}
}
Expand All @@ -288,6 +308,18 @@ public String toString() {
}
}

@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
MvSort mvSort = (MvSort) o;
return Objects.equals(field(), mvSort.field()) && Objects.equals(order(), mvSort.order());
}

@Override
public int hashCode() {
return Objects.hash(field(), order());
}

private static class Evaluator implements EvalOperator.ExpressionEvaluator {
private final BlockFactory blockFactory;
private final EvalOperator.ExpressionEvaluator field;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.elasticsearch.xpack.esql.core.QlIllegalArgumentException;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.Expressions;
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
import org.elasticsearch.xpack.esql.core.expression.TypedAttribute;
import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
import org.elasticsearch.xpack.esql.core.tree.Source;
Expand Down Expand Up @@ -213,7 +212,7 @@ private Query translate(TranslatorHandler handler, Expression spatialExpression,
String name = handler.nameOf(attribute);

try {
Geometry shape = SpatialRelatesUtils.makeGeometryFromLiteral(FoldContext.small() /* TODO remove me */, constantExpression);
Geometry shape = SpatialRelatesUtils.makeGeometryFromLiteral(constantExpression);
return new SpatialRelatesQuery(source(), name, queryRelation(), shape, attribute.dataType());
} catch (IllegalArgumentException e) {
throw new QlIllegalArgumentException(e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.List;
import java.util.function.Function;

import static org.elasticsearch.xpack.esql.core.expression.Foldables.literalValueOf;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.valueOf;

public class SpatialRelatesUtils {
Expand Down Expand Up @@ -168,13 +169,20 @@ private static Geometry asGeometry(BytesRefBlock valueBlock, int position) {
}

/**
* This function is used in two places, when evaluating a spatial constant in the SpatialRelatesFunction, as well as when
* we do lucene-pushdown of spatial functions.
* This function is used when evaluating a spatial constant in the SpatialRelatesFunction
*/
public static Geometry makeGeometryFromLiteral(FoldContext ctx, Expression expr) {
return makeGeometryFromLiteralValue(valueOf(ctx, expr), expr.dataType());
}

/**
* This function is used when we do lucene-pushdown of spatial functions.
* The expression is expected to be folded already and a literal
*/
public static Geometry makeGeometryFromLiteral(Expression expr) {
return makeGeometryFromLiteralValue(literalValueOf(expr), expr.dataType());
}

private static Geometry makeGeometryFromLiteralValue(Object value, DataType dataType) {
if (value instanceof BytesRef bytesRef) {
// Single value expression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import java.util.Objects;

import static java.util.Arrays.asList;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.valueOf;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.literalValueOf;
import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS;
import static org.elasticsearch.xpack.esql.core.type.DataType.IP;
import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG;
Expand Down Expand Up @@ -232,8 +232,8 @@ public Query asQuery(LucenePushdownPredicates pushdownPredicates, TranslatorHand
}

private RangeQuery translate(TranslatorHandler handler) {
Object l = valueOf(FoldContext.small() /* TODO remove me */, lower);
Object u = valueOf(FoldContext.small() /* TODO remove me */, upper);
Object l = literalValueOf(lower);
Object u = literalValueOf(upper);
String format = null;

DataType dataType = value.dataType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
import java.util.Map;

import static org.elasticsearch.common.logging.LoggerMessageFormat.format;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.valueOf;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.extractLiteralOrReturnSelf;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.literalValueOf;
import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME;
import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS;
import static org.elasticsearch.xpack.esql.core.type.DataType.IP;
Expand Down Expand Up @@ -378,7 +379,7 @@ public Expression singleValueField() {
private Query translate(TranslatorHandler handler) {
TypedAttribute attribute = LucenePushdownPredicates.checkIsPushableAttribute(left());
String name = handler.nameOf(attribute);
Object value = valueOf(FoldContext.small() /* TODO remove me */, right());
Object value = extractLiteralOrReturnSelf(right());
String format = null;
boolean isDateLiteralComparison = false;

Expand Down Expand Up @@ -478,7 +479,7 @@ private Query translateOutOfRangeComparisons() {
if ((left() instanceof FieldAttribute) == false || left().dataType().isNumeric() == false) {
return null;
}
Object value = valueOf(FoldContext.small() /* TODO remove me */, right());
Object value = literalValueOf(right());

// Comparisons with multi-values always return null in ESQL.
if (value instanceof List<?>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import java.util.Set;

import static org.elasticsearch.common.logging.LoggerMessageFormat.format;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.valueOf;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.literalValueOf;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT;
import static org.elasticsearch.xpack.esql.core.type.DataType.BOOLEAN;
import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME;
Expand Down Expand Up @@ -491,7 +491,7 @@ private Query translate(LucenePushdownPredicates pushdownPredicates, TranslatorH
queries.add(query);
}
} else {
terms.add(valueOf(FoldContext.small() /* TODO remove me */, rhs));
terms.add(literalValueOf(rhs));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

import java.io.IOException;

import static org.elasticsearch.xpack.esql.core.expression.Foldables.valueOf;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.literalValueOf;

public class InsensitiveEquals extends InsensitiveBinaryComparison {
public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(
Expand Down Expand Up @@ -125,7 +125,7 @@ private void checkInsensitiveComparison() {

private Query translate() {
TypedAttribute attribute = LucenePushdownPredicates.checkIsPushableAttribute(left());
BytesRef value = BytesRefs.toBytesRef(valueOf(FoldContext.small() /* TODO remove me */, right()));
BytesRef value = BytesRefs.toBytesRef(literalValueOf(right()));
String name = LucenePushdownPredicates.pushableAttributeName(attribute);
return new TermQuery(source(), name, value.utf8ToString(), true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import java.util.List;

import static org.elasticsearch.xpack.esql.core.expression.Foldables.literalValueOf;
import static org.elasticsearch.xpack.esql.evaluator.EvalMapper.toEvaluator;

public class InsensitiveEqualsMapper extends ExpressionMapper<InsensitiveEquals> {
Expand All @@ -44,7 +45,7 @@ public final ExpressionEvaluator.Factory map(
var rightEval = toEvaluator(foldCtx, bc.right(), layout, shardContexts);
if (DataType.isString(leftType)) {
if (bc.right().foldable() && DataType.isString(rightType)) {
BytesRef rightVal = BytesRefs.toBytesRef(bc.right().fold(FoldContext.small() /* TODO remove me */));
BytesRef rightVal = BytesRefs.toBytesRef(literalValueOf(bc.right()));
Automaton automaton = InsensitiveEquals.automaton(rightVal);
return dvrCtx -> new InsensitiveEqualsConstantEvaluator(
bc.source(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.elasticsearch.xpack.esql.core.expression.AttributeSet;
import org.elasticsearch.xpack.esql.core.expression.EmptyAttribute;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
import org.elasticsearch.xpack.esql.core.expression.NameId;
import org.elasticsearch.xpack.esql.core.expression.NamedExpression;
import org.elasticsearch.xpack.esql.core.expression.ReferenceAttribute;
Expand All @@ -48,6 +47,7 @@

import static org.elasticsearch.xpack.esql.common.Failure.fail;
import static org.elasticsearch.xpack.esql.core.expression.Expressions.asAttributes;
import static org.elasticsearch.xpack.esql.core.expression.Foldables.literalValueOf;
import static org.elasticsearch.xpack.esql.expression.NamedExpressions.mergeOutputAttributes;

public class Enrich extends UnaryPlan implements GeneratingPlan<Enrich>, PostAnalysisPlanVerificationAware, TelemetryAware, SortAgnostic {
Expand Down Expand Up @@ -152,7 +152,7 @@ public void writeTo(StreamOutput out) throws IOException {
out.writeNamedWriteable(policyName());
out.writeNamedWriteable(matchField());
if (out.getTransportVersion().before(TransportVersions.V_8_13_0)) {
out.writeString(BytesRefs.toString(policyName().fold(FoldContext.small() /* TODO remove me */))); // old policy name
out.writeString(BytesRefs.toString(literalValueOf(policyName()))); // old policy name
}
policy().writeTo(out);
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_13_0)) {
Expand Down
Loading