diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expressions.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expressions.java index 739333ded0fde..50a0c664812f8 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expressions.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expressions.java @@ -116,6 +116,15 @@ public static List fold(FoldContext ctx, List exps return folded; } + public static boolean literals(List exps) { + for (Expression exp : exps) { + if (exp instanceof Literal == false) { + return false; + } + } + return true; + } + public static AttributeSet references(List exps) { if (exps.isEmpty()) { return AttributeSet.EMPTY; diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Foldables.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Foldables.java index 233113c3fe1b8..106be988b2fe6 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Foldables.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Foldables.java @@ -16,4 +16,12 @@ public static Object valueOf(FoldContext ctx, Expression e) { } throw new QlIllegalArgumentException("Cannot determine value for {}", e); } + + public static Object valueOfLiteral(Expression e) { + if (e instanceof Literal literal) { + return literal.value(); + } + + throw new QlIllegalArgumentException("Expected a Literal but received [" + e + "]"); + } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 15bbe29cb0b89..19a19e0505abf 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -18,7 +18,7 @@ import org.elasticsearch.xpack.esql.capabilities.TranslationAware; 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.Foldables; import org.elasticsearch.xpack.esql.core.expression.Nullability; import org.elasticsearch.xpack.esql.core.expression.TypeResolutions; import org.elasticsearch.xpack.esql.core.expression.function.Function; @@ -114,7 +114,7 @@ public Expression query() { * @return query expression as an object */ public Object queryAsObject() { - Object queryAsObject = query().fold(FoldContext.small() /* TODO remove me */); + Object queryAsObject = Foldables.valueOfLiteral(query()); return BytesRefs.toString(queryAsObject); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java index 3b3df2e376c9d..3f7e41f01b7c0 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java @@ -21,7 +21,7 @@ import org.elasticsearch.xpack.esql.core.expression.EntryExpression; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; -import org.elasticsearch.xpack.esql.core.expression.FoldContext; +import org.elasticsearch.xpack.esql.core.expression.Foldables; import org.elasticsearch.xpack.esql.core.expression.Literal; import org.elasticsearch.xpack.esql.core.expression.MapExpression; import org.elasticsearch.xpack.esql.core.querydsl.query.Query; @@ -453,7 +453,7 @@ public BiConsumer postAnalysisPlanVerification() { @Override public Object queryAsObject() { - Object queryAsObject = query().fold(FoldContext.small() /* TODO remove me */); + Object queryAsObject = Foldables.valueOfLiteral(query()); // Convert BytesRef to string for string-based values if (queryAsObject instanceof BytesRef bytesRef) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatch.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatch.java index aae01ab774efa..02585f7e8e560 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatch.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatch.java @@ -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; @@ -189,7 +189,11 @@ public Query asQuery(TranslatorHandler handler) { Check.isTrue(Expressions.foldable(matches), "Expected foldable matches, but got [{}]", matches); String targetFieldName = handler.nameOf(fa.exactAttribute()); - Set set = new LinkedHashSet<>(Expressions.fold(FoldContext.small() /* TODO remove me */, matches)); + + Set set = new LinkedHashSet<>(matches.size()); + for (Expression exp : matches) { + set.add(Foldables.valueOfLiteral(exp)); + } return new TermsQuery(source(), targetFieldName, set); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesFunction.java index 295116a5e99c2..918f9db53e77a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesFunction.java @@ -26,7 +26,7 @@ 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.Foldables; 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; @@ -210,7 +210,10 @@ 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.makeGeometryFromLiteralValue( + Foldables.valueOfLiteral(constantExpression), + constantExpression.dataType() + ); return new SpatialRelatesQuery(source(), name, queryRelation(), shape, attribute.dataType()); } catch (IllegalArgumentException e) { throw new QlIllegalArgumentException(e.getMessage(), e); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesUtils.java index 1b06c6dfd3dd5..a9e1b487e4b63 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesUtils.java @@ -175,7 +175,7 @@ public static Geometry makeGeometryFromLiteral(FoldContext ctx, Expression expr) return makeGeometryFromLiteralValue(valueOf(ctx, expr), expr.dataType()); } - private static Geometry makeGeometryFromLiteralValue(Object value, DataType dataType) { + public static Geometry makeGeometryFromLiteralValue(Object value, DataType dataType) { if (value instanceof BytesRef bytesRef) { // Single value expression return SpatialCoordinateTypes.UNSPECIFIED.wkbToGeometry(bytesRef); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/EndsWith.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/EndsWith.java index b3d50d7b572fb..218121d37c7a3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/EndsWith.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/EndsWith.java @@ -18,7 +18,8 @@ import org.elasticsearch.xpack.esql.capabilities.TranslationAware; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; -import org.elasticsearch.xpack.esql.core.expression.FoldContext; +import org.elasticsearch.xpack.esql.core.expression.Foldables; +import org.elasticsearch.xpack.esql.core.expression.Literal; import org.elasticsearch.xpack.esql.core.querydsl.query.Query; import org.elasticsearch.xpack.esql.core.querydsl.query.WildcardQuery; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -140,16 +141,14 @@ public ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { @Override public boolean translatable(LucenePushdownPredicates pushdownPredicates) { - return pushdownPredicates.isPushableAttribute(str) && suffix.foldable(); + return pushdownPredicates.isPushableAttribute(str) && suffix instanceof Literal; } @Override public Query asQuery(TranslatorHandler handler) { LucenePushdownPredicates.checkIsPushableAttribute(str); var fieldName = handler.nameOf(str instanceof FieldAttribute fa ? fa.exactAttribute() : str); - - // TODO: Get the real FoldContext here - var wildcardQuery = "*" + QueryParser.escape(BytesRefs.toString(suffix.fold(FoldContext.small()))); + var wildcardQuery = "*" + QueryParser.escape(BytesRefs.toString(Foldables.valueOfLiteral(suffix))); return new WildcardQuery(source(), fieldName, wildcardQuery); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/StartsWith.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/StartsWith.java index 9ab552576dbbb..eb44d5f8258c5 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/StartsWith.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/StartsWith.java @@ -18,7 +18,8 @@ import org.elasticsearch.xpack.esql.capabilities.TranslationAware; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; -import org.elasticsearch.xpack.esql.core.expression.FoldContext; +import org.elasticsearch.xpack.esql.core.expression.Foldables; +import org.elasticsearch.xpack.esql.core.expression.Literal; import org.elasticsearch.xpack.esql.core.querydsl.query.Query; import org.elasticsearch.xpack.esql.core.querydsl.query.WildcardQuery; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -137,16 +138,14 @@ public ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { @Override public boolean translatable(LucenePushdownPredicates pushdownPredicates) { - return pushdownPredicates.isPushableAttribute(str) && prefix.foldable(); + return pushdownPredicates.isPushableAttribute(str) && prefix instanceof Literal; } @Override public Query asQuery(TranslatorHandler handler) { LucenePushdownPredicates.checkIsPushableAttribute(str); var fieldName = handler.nameOf(str instanceof FieldAttribute fa ? fa.exactAttribute() : str); - - // TODO: Get the real FoldContext here - var wildcardQuery = QueryParser.escape(BytesRefs.toString(prefix.fold(FoldContext.small()))) + "*"; + var wildcardQuery = QueryParser.escape(BytesRefs.toString(Foldables.valueOfLiteral(prefix))) + "*"; return new WildcardQuery(source(), fieldName, wildcardQuery); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/Range.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/Range.java index 4da10c5ec7b8c..26f13a5b61fc0 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/Range.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/Range.java @@ -30,7 +30,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.valueOfLiteral; import static org.elasticsearch.xpack.esql.core.type.DataType.IP; import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG; import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION; @@ -196,7 +196,7 @@ public boolean equals(Object obj) { @Override public boolean translatable(LucenePushdownPredicates pushdownPredicates) { - return pushdownPredicates.isPushableAttribute(value) && lower.foldable() && upper.foldable(); + return pushdownPredicates.isPushableAttribute(value) && lower instanceof Literal && upper instanceof Literal; } @Override @@ -205,8 +205,8 @@ public Query asQuery(TranslatorHandler handler) { } 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 = valueOfLiteral(lower); + Object u = valueOfLiteral(upper); String format = null; DataType dataType = value.dataType(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EsqlBinaryComparison.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EsqlBinaryComparison.java index fc69f4dc19d72..6dc130fb6c6c8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EsqlBinaryComparison.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EsqlBinaryComparison.java @@ -20,6 +20,7 @@ import org.elasticsearch.xpack.esql.core.expression.Expressions; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; 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.TypedAttribute; import org.elasticsearch.xpack.esql.core.expression.predicate.operator.comparison.BinaryComparison; @@ -49,7 +50,7 @@ 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.valueOfLiteral; import static org.elasticsearch.xpack.esql.core.type.DataType.IP; import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG; import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION; @@ -322,7 +323,7 @@ public static String formatIncompatibleTypesMessage(DataType leftType, DataType @Override public boolean translatable(LucenePushdownPredicates pushdownPredicates) { - if (right().foldable()) { + if (right() instanceof Literal) { if (pushdownPredicates.isPushableFieldAttribute(left())) { return true; } @@ -371,7 +372,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 = valueOfLiteral(right()); String format = null; boolean isDateLiteralComparison = false; @@ -452,7 +453,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 = valueOfLiteral(right()); // Comparisons with multi-values always return null in ESQL. if (value instanceof List) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/In.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/In.java index d5969d3a0ab37..13308495a3fd8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/In.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/In.java @@ -20,6 +20,7 @@ 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.expression.TypedAttribute; import org.elasticsearch.xpack.esql.core.expression.predicate.operator.comparison.Comparisons; import org.elasticsearch.xpack.esql.core.querydsl.query.Query; @@ -50,7 +51,6 @@ 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.TypeResolutions.ParamOrdinal.DEFAULT; import static org.elasticsearch.xpack.esql.core.type.DataType.BOOLEAN; import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; @@ -459,7 +459,7 @@ static boolean process(BitSet nulls, BitSet mvs, BytesRef lhs, BytesRef[] rhs) { @Override public boolean translatable(LucenePushdownPredicates pushdownPredicates) { - return pushdownPredicates.isPushableAttribute(value) && Expressions.foldable(list()); + return pushdownPredicates.isPushableAttribute(value) && Expressions.literals(list()); } @Override @@ -487,7 +487,7 @@ private Query translate(TranslatorHandler handler) { queries.add(query); } } else { - terms.add(valueOf(FoldContext.small() /* TODO remove me */, rhs)); + terms.add(Foldables.valueOfLiteral(rhs)); } } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/InsensitiveEquals.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/InsensitiveEquals.java index 3a9ca27637db8..ef6ab581625d3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/InsensitiveEquals.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/InsensitiveEquals.java @@ -18,6 +18,8 @@ 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.expression.Literal; import org.elasticsearch.xpack.esql.core.expression.TypeResolutions; import org.elasticsearch.xpack.esql.core.expression.TypedAttribute; import org.elasticsearch.xpack.esql.core.querydsl.query.Query; @@ -30,8 +32,6 @@ import java.io.IOException; -import static org.elasticsearch.xpack.esql.core.expression.Foldables.valueOf; - public class InsensitiveEquals extends InsensitiveBinaryComparison { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( Expression.class, @@ -98,7 +98,7 @@ public Boolean fold(FoldContext ctx) { @Override public boolean translatable(LucenePushdownPredicates pushdownPredicates) { - return pushdownPredicates.isPushableFieldAttribute(left()) && right().foldable(); + return pushdownPredicates.isPushableFieldAttribute(left()) && right() instanceof Literal; } @Override @@ -120,7 +120,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(Foldables.valueOfLiteral(right())); String name = LucenePushdownPredicates.pushableAttributeName(attribute); return new TermQuery(source(), name, value.utf8ToString(), true); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/TranslatorHandler.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/TranslatorHandler.java index f7f09d36a4296..3482feb870f56 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/TranslatorHandler.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/TranslatorHandler.java @@ -13,6 +13,7 @@ import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.Expressions; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; +import org.elasticsearch.xpack.esql.core.expression.Literal; import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute; import org.elasticsearch.xpack.esql.core.querydsl.query.Query; import org.elasticsearch.xpack.esql.querydsl.query.SingleValueQuery; @@ -53,4 +54,18 @@ private static Query wrapFunctionQuery(Expression field, Query query) { public String nameOf(Expression e) { return Expressions.name(e); } + + /** + * Returns the value of the given expression, as long as it's a Literal. + *

+ * At this stage of the planning, foldable expressions should be literals. + *

+ */ + public Object valueOf(Expression e) { + if (e instanceof Literal literal) { + return literal.value(); + } + + throw new EsqlIllegalArgumentException("Expected a Literal but received [" + e + "]"); + } }