Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -38,7 +38,6 @@
import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG;
import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION;
import static org.elasticsearch.xpack.esql.core.type.DataType.isDateTime;
import static org.elasticsearch.xpack.esql.core.type.DataType.isPrimitiveAndSupported;
import static org.elasticsearch.xpack.esql.core.type.DataType.isString;
import static org.elasticsearch.xpack.esql.core.util.NumericUtils.UNSIGNED_LONG_MAX;
import static org.elasticsearch.xpack.esql.core.util.NumericUtils.inUnsignedLongRange;
Expand All @@ -51,85 +50,6 @@ public final class DataTypeConverter {

private DataTypeConverter() {}

/**
* Returns the type compatible with both left and right types
* <p>
* If one of the types is null - returns another type
* If both types are numeric - returns type with the highest precision int &lt; long &lt; float &lt; double
* If one of the types is string and another numeric - returns numeric
*/
public static DataType commonType(DataType left, DataType right) {
if (left == right) {
return left;
}
if (left == NULL) {
return right;
}
if (right == NULL) {
return left;
}
if (isString(left) && isString(right)) {
if (left == TEXT || right == TEXT) {
return TEXT;
}
if (left == KEYWORD) {
return KEYWORD;
}
return right;
}
if (left.isNumeric() && right.isNumeric()) {
int lsize = left.estimatedSize().orElseThrow();
int rsize = right.estimatedSize().orElseThrow();
// if one is int
if (left.isWholeNumber()) {
// promote the highest int
if (right.isWholeNumber()) {
if (left == UNSIGNED_LONG || right == UNSIGNED_LONG) {
return UNSIGNED_LONG;
}
return lsize > rsize ? left : right;
}
// promote the rational
return right;
}
// try the other side
if (right.isWholeNumber()) {
return left;
}
// promote the highest rational
return lsize > rsize ? left : right;
}
if (isString(left)) {
if (right.isNumeric()) {
return right;
}
}
if (isString(right)) {
if (left.isNumeric()) {
return left;
}
}

if (isDateTime(left) && isDateTime(right)) {
return DATETIME;
}

// none found
return null;
}

/**
* Returns true if the from type can be converted to the to type, false - otherwise
*/
public static boolean canConvert(DataType from, DataType to) {
// Special handling for nulls and if conversion is not requires
if (from == to || from == NULL) {
return true;
}
// only primitives are supported so far
return isPrimitiveAndSupported(from) && isPrimitiveAndSupported(to) && converterFor(from, to) != null;
}

/**
* Get the conversion from one type to another.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.elasticsearch.compute.ann.Evaluator;
import org.elasticsearch.compute.ann.Fixed;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.BinaryComparisonInversible;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.core.util.NumericUtils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
package org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic;
package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;

import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal;
import org.elasticsearch.xpack.esql.core.expression.predicate.BinaryOperator;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.BinaryArithmeticOperation;
import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.core.type.DataType;
import org.elasticsearch.xpack.esql.core.type.DataTypeConverter;

import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNumeric;
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.commonType;

public abstract class ArithmeticOperation extends BinaryOperator<Object, Object, Object, BinaryArithmeticOperation> {

Expand All @@ -36,7 +37,7 @@ public ArithmeticOperation swapLeftAndRight() {
@Override
public DataType dataType() {
if (dataType == null) {
dataType = DataTypeConverter.commonType(left().dataType(), right().dataType());
dataType = commonType(left().dataType(), right().dataType());
}
return dataType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

package org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic;
package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic;

import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.tree.Source;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.compute.ann.Evaluator;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.BinaryComparisonInversible;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.core.type.DataType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@
import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator;
import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.ArithmeticOperation;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.BinaryArithmeticOperation;
import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.core.type.DataType;
import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper;
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cast;
import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
import org.elasticsearch.xpack.esql.type.EsqlDataTypeRegistry;

import java.io.IOException;
import java.util.List;
Expand All @@ -31,6 +29,7 @@
import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER;
import static org.elasticsearch.xpack.esql.core.type.DataType.LONG;
import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG;
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.commonType;

public abstract class EsqlArithmeticOperation extends ArithmeticOperation implements EvaluatorMapper {
public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
Expand Down Expand Up @@ -133,7 +132,7 @@ public Object fold() {

public DataType dataType() {
if (dataType == null) {
dataType = EsqlDataTypeRegistry.INSTANCE.commonType(left().dataType(), right().dataType());
dataType = commonType(left().dataType(), right().dataType());
}
return dataType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.compute.ann.Evaluator;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.BinaryComparisonInversible;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.core.util.NumericUtils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.elasticsearch.compute.ann.Evaluator;
import org.elasticsearch.compute.ann.Fixed;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.BinaryComparisonInversible;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.core.type.DataType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cast;
import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.EsqlArithmeticOperation;
import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
import org.elasticsearch.xpack.esql.type.EsqlDataTypeRegistry;

import java.io.IOException;
import java.time.ZoneId;
Expand All @@ -32,6 +31,7 @@

import static org.elasticsearch.common.logging.LoggerMessageFormat.format;
import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG;
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.commonType;

public abstract class EsqlBinaryComparison extends BinaryComparison implements EvaluatorMapper {
public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
Expand Down Expand Up @@ -172,7 +172,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(
Function<Expression, EvalOperator.ExpressionEvaluator.Factory> toEvaluator
) {
// Our type is always boolean, so figure out the evaluator type from the inputs
DataType commonType = EsqlDataTypeRegistry.INSTANCE.commonType(left().dataType(), right().dataType());
DataType commonType = commonType(left().dataType(), right().dataType());
EvalOperator.ExpressionEvaluator.Factory lhs;
EvalOperator.ExpressionEvaluator.Factory rhs;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import org.elasticsearch.xpack.esql.expression.function.scalar.EsqlScalarFunction;
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cast;
import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
import org.elasticsearch.xpack.esql.type.EsqlDataTypeRegistry;
import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter;

import java.io.IOException;
import java.util.BitSet;
Expand Down Expand Up @@ -269,7 +269,7 @@ private DataType commonType() {
break;
}
}
commonType = EsqlDataTypeRegistry.INSTANCE.commonType(commonType, e.dataType());
commonType = EsqlDataTypeConverter.commonType(commonType, e.dataType());
}
return commonType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@

import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.Literal;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.ArithmeticOperation;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.arithmetic.BinaryComparisonInversible;
import org.elasticsearch.xpack.esql.core.expression.predicate.operator.comparison.BinaryComparison;
import org.elasticsearch.xpack.esql.core.type.DataType;
import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.ArithmeticOperation;
import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.BinaryComparisonInversible;
import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Neg;
import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Sub;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import static org.elasticsearch.xpack.esql.core.type.DataType.CARTESIAN_POINT;
import static org.elasticsearch.xpack.esql.core.type.DataType.CARTESIAN_SHAPE;
import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME;
import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_PERIOD;
import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE;
import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT;
import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE;
Expand All @@ -67,9 +68,14 @@
import static org.elasticsearch.xpack.esql.core.type.DataType.LONG;
import static org.elasticsearch.xpack.esql.core.type.DataType.NULL;
import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT;
import static org.elasticsearch.xpack.esql.core.type.DataType.TIME_DURATION;
import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG;
import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION;
import static org.elasticsearch.xpack.esql.core.type.DataType.isPrimitiveAndSupported;
import static org.elasticsearch.xpack.esql.core.type.DataType.isDateTime;
import static org.elasticsearch.xpack.esql.core.type.DataType.isDateTimeOrTemporal;
import static org.elasticsearch.xpack.esql.core.type.DataType.isNullOrDatePeriod;
import static org.elasticsearch.xpack.esql.core.type.DataType.isNullOrTemporalAmount;
import static org.elasticsearch.xpack.esql.core.type.DataType.isNullOrTimeDuration;
import static org.elasticsearch.xpack.esql.core.type.DataType.isString;
import static org.elasticsearch.xpack.esql.core.type.DataTypeConverter.safeDoubleToLong;
import static org.elasticsearch.xpack.esql.core.type.DataTypeConverter.safeToInt;
Expand Down Expand Up @@ -107,18 +113,6 @@ public class EsqlDataTypeConverter {
entry(VERSION, ToVersion::new)
);

/**
* Returns true if the from type can be converted to the to type, false - otherwise
*/
public static boolean canConvert(DataType from, DataType to) {
// Special handling for nulls and if conversion is not requires
if (from == to || from == NULL) {
return true;
}
// only primitives are supported so far
return isPrimitiveAndSupported(from) && isPrimitiveAndSupported(to) && converterFor(from, to) != null;
}

public static Converter converterFor(DataType from, DataType to) {
// TODO move EXPRESSION_TO_LONG here if there is no regression
if (isString(from)) {
Expand Down Expand Up @@ -230,8 +224,63 @@ public static Object convert(Object value, DataType dataType) {
return converter.convert(value);
}

/**
* Returns the type compatible with both left and right types
* <p>
* If one of the types is null - returns another type
* If both types are numeric - returns type with the highest precision int &lt; long &lt; float &lt; double
*/
public static DataType commonType(DataType left, DataType right) {
return DataTypeConverter.commonType(left, right);
if (left == right) {
return left;
}
if (left == NULL) {
return right;
}
if (right == NULL) {
return left;
}
if (isDateTimeOrTemporal(left) || isDateTimeOrTemporal(right)) {
if ((isDateTime(left) && isNullOrTemporalAmount(right)) || (isNullOrTemporalAmount(left) && isDateTime(right))) {
return DATETIME;
}
if (isNullOrTimeDuration(left) && isNullOrTimeDuration(right)) {
return TIME_DURATION;
}
if (isNullOrDatePeriod(left) && isNullOrDatePeriod(right)) {
return DATE_PERIOD;
}
}
if (isString(left) && isString(right)) {
if (left == TEXT || right == TEXT) {
return TEXT;
}
return right;
}
if (left.isNumeric() && right.isNumeric()) {
int lsize = left.estimatedSize().orElseThrow();
int rsize = right.estimatedSize().orElseThrow();
// if one is int
if (left.isWholeNumber()) {
// promote the highest int
if (right.isWholeNumber()) {
if (left == UNSIGNED_LONG || right == UNSIGNED_LONG) {
return UNSIGNED_LONG;
}
return lsize > rsize ? left : right;
}
// promote the rational
return right;
}
// try the other side
if (right.isWholeNumber()) {
return left;
}
// promote the highest rational
return lsize > rsize ? left : right;
}
// none found
return null;
}

// generally supporting abbreviations from https://en.wikipedia.org/wiki/Unit_of_time
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@
import org.elasticsearch.index.mapper.TimeSeriesParams;
import org.elasticsearch.xpack.esql.core.type.DataType;

import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME;
import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_PERIOD;
import static org.elasticsearch.xpack.esql.core.type.DataType.TIME_DURATION;
import static org.elasticsearch.xpack.esql.core.type.DataType.isDateTime;
import static org.elasticsearch.xpack.esql.core.type.DataType.isDateTimeOrTemporal;
import static org.elasticsearch.xpack.esql.core.type.DataType.isNullOrDatePeriod;
import static org.elasticsearch.xpack.esql.core.type.DataType.isNullOrTemporalAmount;
import static org.elasticsearch.xpack.esql.core.type.DataType.isNullOrTimeDuration;

public class EsqlDataTypeRegistry {

public static final EsqlDataTypeRegistry INSTANCE = new EsqlDataTypeRegistry();
Expand All @@ -35,19 +26,4 @@ public DataType fromEs(String typeName, TimeSeriesParams.MetricType metricType)
*/
return metricType == TimeSeriesParams.MetricType.COUNTER ? type.widenSmallNumeric().counter() : type;
}

public DataType commonType(DataType left, DataType right) {
if (isDateTimeOrTemporal(left) || isDateTimeOrTemporal(right)) {
if ((isDateTime(left) && isNullOrTemporalAmount(right)) || (isNullOrTemporalAmount(left) && isDateTime(right))) {
return DATETIME;
}
if (isNullOrTimeDuration(left) && isNullOrTimeDuration(right)) {
return TIME_DURATION;
}
if (isNullOrDatePeriod(left) && isNullOrDatePeriod(right)) {
return DATE_PERIOD;
}
}
return EsqlDataTypeConverter.commonType(left, right);
}
}
Loading