diff --git a/core/src/main/java/org/opensearch/sql/data/model/AbstractExprValue.java b/core/src/main/java/org/opensearch/sql/data/model/AbstractExprValue.java index 4933592564..6a823dff68 100644 --- a/core/src/main/java/org/opensearch/sql/data/model/AbstractExprValue.java +++ b/core/src/main/java/org/opensearch/sql/data/model/AbstractExprValue.java @@ -19,9 +19,11 @@ public abstract class AbstractExprValue implements ExprValue { public int compareTo(ExprValue other) { if (this.isNull() || this.isMissing() || other.isNull() || other.isMissing()) { throw new IllegalStateException( - String.format("[BUG] Unreachable, Comparing with NULL or MISSING is undefined")); + "[BUG] Unreachable, Comparing with NULL or MISSING is undefined"); } - if ((this.isNumber() && other.isNumber()) || this.type() == other.type()) { + if ((this.isNumber() && other.isNumber()) + || (this.isDateTime() && other.isDateTime()) + || this.type() == other.type()) { return compare(other); } else { throw new ExpressionEvaluationException( diff --git a/core/src/main/java/org/opensearch/sql/data/model/ExprDateValue.java b/core/src/main/java/org/opensearch/sql/data/model/ExprDateValue.java index 7617e156ba..b0c7a02c88 100644 --- a/core/src/main/java/org/opensearch/sql/data/model/ExprDateValue.java +++ b/core/src/main/java/org/opensearch/sql/data/model/ExprDateValue.java @@ -13,7 +13,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -69,7 +68,12 @@ public LocalDateTime datetimeValue() { @Override public Instant timestampValue() { - return ZonedDateTime.of(date, timeValue(), ZoneId.systemDefault()).toInstant(); + return ZonedDateTime.of(date, timeValue(), ExprTimestampValue.ZONE).toInstant(); + } + + @Override + public boolean isDateTime() { + return true; } @Override diff --git a/core/src/main/java/org/opensearch/sql/data/model/ExprDatetimeValue.java b/core/src/main/java/org/opensearch/sql/data/model/ExprDatetimeValue.java index f5f80f133f..8a9a544cd9 100644 --- a/core/src/main/java/org/opensearch/sql/data/model/ExprDatetimeValue.java +++ b/core/src/main/java/org/opensearch/sql/data/model/ExprDatetimeValue.java @@ -11,7 +11,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; @@ -71,7 +70,12 @@ public LocalTime timeValue() { @Override public Instant timestampValue() { - return ZonedDateTime.of(datetime, ZoneId.of("UTC")).toInstant(); + return ZonedDateTime.of(datetime, ExprTimestampValue.ZONE).toInstant(); + } + + @Override + public boolean isDateTime() { + return true; } @Override diff --git a/core/src/main/java/org/opensearch/sql/data/model/ExprTimeValue.java b/core/src/main/java/org/opensearch/sql/data/model/ExprTimeValue.java index 6cc4021d2e..15bd1d7dae 100644 --- a/core/src/main/java/org/opensearch/sql/data/model/ExprTimeValue.java +++ b/core/src/main/java/org/opensearch/sql/data/model/ExprTimeValue.java @@ -13,7 +13,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeParseException; import java.util.Objects; @@ -21,6 +20,7 @@ import org.opensearch.sql.data.type.ExprCoreType; import org.opensearch.sql.data.type.ExprType; import org.opensearch.sql.exception.SemanticCheckException; +import org.opensearch.sql.expression.function.FunctionProperties; /** * Expression Time Value. @@ -57,6 +57,24 @@ public LocalTime timeValue() { return time; } + public LocalDate dateValue(FunctionProperties functionProperties) { + return LocalDate.now(functionProperties.getQueryStartClock()); + } + + public LocalDateTime datetimeValue(FunctionProperties functionProperties) { + return LocalDateTime.of(dateValue(functionProperties), timeValue()); + } + + public Instant timestampValue(FunctionProperties functionProperties) { + return ZonedDateTime.of(dateValue(functionProperties), timeValue(), ExprTimestampValue.ZONE) + .toInstant(); + } + + @Override + public boolean isDateTime() { + return true; + } + @Override public String toString() { return String.format("TIME '%s'", value()); diff --git a/core/src/main/java/org/opensearch/sql/data/model/ExprTimestampValue.java b/core/src/main/java/org/opensearch/sql/data/model/ExprTimestampValue.java index 219a4c2663..7e6e75ed0d 100644 --- a/core/src/main/java/org/opensearch/sql/data/model/ExprTimestampValue.java +++ b/core/src/main/java/org/opensearch/sql/data/model/ExprTimestampValue.java @@ -30,7 +30,7 @@ public class ExprTimestampValue extends AbstractExprValue { /** * todo. only support UTC now. */ - private static final ZoneId ZONE = ZoneId.of("UTC"); + public static final ZoneId ZONE = ZoneId.of("UTC"); private final Instant timestamp; @@ -81,6 +81,11 @@ public LocalDateTime datetimeValue() { return timestamp.atZone(ZONE).toLocalDateTime(); } + @Override + public boolean isDateTime() { + return true; + } + @Override public String toString() { return String.format("TIMESTAMP '%s'", value()); diff --git a/core/src/main/java/org/opensearch/sql/data/model/ExprValue.java b/core/src/main/java/org/opensearch/sql/data/model/ExprValue.java index 53909184e8..b74cc4fe53 100644 --- a/core/src/main/java/org/opensearch/sql/data/model/ExprValue.java +++ b/core/src/main/java/org/opensearch/sql/data/model/ExprValue.java @@ -60,6 +60,15 @@ default boolean isNumber() { return false; } + /** + * Is Number value. + * + * @return true: is a datetime value, otherwise false + */ + default boolean isDateTime() { + return false; + } + /** * Get the {@link BindingTuple}. */ diff --git a/core/src/main/java/org/opensearch/sql/data/model/ExprValueUtils.java b/core/src/main/java/org/opensearch/sql/data/model/ExprValueUtils.java index 407b6df5b3..44e0350d31 100644 --- a/core/src/main/java/org/opensearch/sql/data/model/ExprValueUtils.java +++ b/core/src/main/java/org/opensearch/sql/data/model/ExprValueUtils.java @@ -6,6 +6,10 @@ package org.opensearch.sql.data.model; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.temporal.TemporalAmount; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -61,6 +65,22 @@ public static ExprValue intervalValue(TemporalAmount value) { return new ExprIntervalValue(value); } + public static ExprValue dateValue(LocalDate value) { + return new ExprDateValue(value); + } + + public static ExprValue datetimeValue(LocalDateTime value) { + return new ExprDatetimeValue(value); + } + + public static ExprValue timeValue(LocalTime value) { + return new ExprTimeValue(value); + } + + public static ExprValue timestampValue(Instant value) { + return new ExprTimestampValue(value); + } + /** * {@link ExprTupleValue} constructor. */ @@ -115,6 +135,14 @@ public static ExprValue fromObjectValue(Object o) { return stringValue((String) o); } else if (o instanceof Float) { return floatValue((Float) o); + } else if (o instanceof LocalDate) { + return dateValue((LocalDate) o); + } else if (o instanceof LocalDateTime) { + return datetimeValue((LocalDateTime) o); + } else if (o instanceof LocalTime) { + return timeValue((LocalTime) o); + } else if (o instanceof Instant) { + return timestampValue((Instant) o); } else { throw new ExpressionEvaluationException("unsupported object " + o.getClass()); } diff --git a/core/src/main/java/org/opensearch/sql/expression/DSL.java b/core/src/main/java/org/opensearch/sql/expression/DSL.java index f5fd1e3315..e2554acb23 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -502,28 +502,52 @@ public static FunctionExpression not(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.NOT, expressions); } + public static FunctionExpression equal(FunctionProperties fp, Expression... expressions) { + return compile(fp, BuiltinFunctionName.EQUAL, expressions); + } + public static FunctionExpression equal(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.EQUAL, expressions); + return equal(FunctionProperties.None, expressions); + } + + public static FunctionExpression notequal(FunctionProperties fp, Expression... expressions) { + return compile(fp, BuiltinFunctionName.NOTEQUAL, expressions); } public static FunctionExpression notequal(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.NOTEQUAL, expressions); + return notequal(FunctionProperties.None, expressions); + } + + public static FunctionExpression less(FunctionProperties fp, Expression... expressions) { + return compile(fp, BuiltinFunctionName.LESS, expressions); } public static FunctionExpression less(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.LESS, expressions); + return less(FunctionProperties.None, expressions); + } + + public static FunctionExpression lte(FunctionProperties fp, Expression... expressions) { + return compile(fp, BuiltinFunctionName.LTE, expressions); } public static FunctionExpression lte(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.LTE, expressions); + return lte(FunctionProperties.None, expressions); + } + + public static FunctionExpression greater(FunctionProperties fp, Expression... expressions) { + return compile(fp, BuiltinFunctionName.GREATER, expressions); } public static FunctionExpression greater(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.GREATER, expressions); + return greater(FunctionProperties.None, expressions); + } + + public static FunctionExpression gte(FunctionProperties fp, Expression... expressions) { + return compile(fp, BuiltinFunctionName.GTE, expressions); } public static FunctionExpression gte(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.GTE, expressions); + return gte(FunctionProperties.None, expressions); } public static FunctionExpression like(Expression... expressions) { diff --git a/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java b/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java index 5b182f76f4..5938eb85d5 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java @@ -137,6 +137,52 @@ public String toString() { }; } + /** + * Implementation of a function that takes two arguments, returns a value, and + * requires FunctionProperties to complete. + * + * @param function {@link ExprValue} based unary function. + * @param returnType return type. + * @param args1Type first argument type. + * @param args2Type second argument type. + * @return Unary Function Implementation. + */ + public static SerializableFunction> + implWithProperties( + SerializableTriFunction function, + ExprType returnType, + ExprType args1Type, + ExprType args2Type) { + + return functionName -> { + FunctionSignature functionSignature = + new FunctionSignature(functionName, Arrays.asList(args1Type, args2Type)); + FunctionBuilder functionBuilder = + (functionProperties, arguments) -> new FunctionExpression(functionName, arguments) { + @Override + public ExprValue valueOf(Environment valueEnv) { + ExprValue arg1 = arguments.get(0).valueOf(valueEnv); + ExprValue arg2 = arguments.get(1).valueOf(valueEnv); + return function.apply(functionProperties, arg1, arg2); + } + + @Override + public ExprType type() { + return returnType; + } + + @Override + public String toString() { + return String.format("%s(%s)", functionName, + arguments.stream() + .map(Object::toString) + .collect(Collectors.joining(", "))); + } + }; + return Pair.of(functionSignature, functionBuilder); + }; + } + /** * No Arg Function Implementation. * @@ -317,4 +363,22 @@ public SerializableTriFunction nullM } }; } + + /** + * Wrapper for the ExprValue function that takes 2 arguments and is aware of FunctionProperties, + * with default NULL and MISSING handling. + */ + public static SerializableTriFunction + nullMissingHandlingWithProperties( + SerializableTriFunction implementation) { + return (functionProperties, v1, v2) -> { + if (v1.isMissing() || v2.isMissing()) { + return ExprValueUtils.missingValue(); + } else if (v1.isNull() || v2.isNull()) { + return ExprValueUtils.nullValue(); + } else { + return implementation.apply(functionProperties, v1, v2); + } + }; + } } diff --git a/core/src/main/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperator.java b/core/src/main/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperator.java index 99399249c2..23547e8d47 100644 --- a/core/src/main/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperator.java +++ b/core/src/main/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperator.java @@ -11,13 +11,25 @@ import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_NULL; import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_TRUE; import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN; +import static org.opensearch.sql.data.type.ExprCoreType.DATE; +import static org.opensearch.sql.data.type.ExprCoreType.DATETIME; import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; import static org.opensearch.sql.data.type.ExprCoreType.STRING; +import static org.opensearch.sql.data.type.ExprCoreType.TIME; +import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP; +import static org.opensearch.sql.expression.function.FunctionDSL.impl; +import static org.opensearch.sql.expression.function.FunctionDSL.implWithProperties; +import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandling; +import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandlingWithProperties; +import static org.opensearch.sql.utils.DateTimeUtils.extractDateTime; import com.google.common.collect.ImmutableTable; import com.google.common.collect.Table; +import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.experimental.UtilityClass; +import org.apache.commons.lang3.tuple.Pair; import org.opensearch.sql.data.model.ExprBooleanValue; import org.opensearch.sql.data.model.ExprValue; import org.opensearch.sql.data.type.ExprCoreType; @@ -25,6 +37,8 @@ import org.opensearch.sql.expression.function.BuiltinFunctionRepository; import org.opensearch.sql.expression.function.DefaultFunctionResolver; import org.opensearch.sql.expression.function.FunctionDSL; +import org.opensearch.sql.expression.function.FunctionName; +import org.opensearch.sql.expression.function.SerializableBiFunction; import org.opensearch.sql.utils.OperatorUtils; /** @@ -141,116 +155,80 @@ public static void register(BuiltinFunctionRepository repository) { .build(); private static DefaultFunctionResolver and() { - return FunctionDSL.define(BuiltinFunctionName.AND.getName(), FunctionDSL - .impl((v1, v2) -> lookupTableFunction(v1, v2, andTable), BOOLEAN, BOOLEAN, - BOOLEAN)); + return FunctionDSL.define(BuiltinFunctionName.AND.getName(), + impl((v1, v2) -> lookupTableFunction(v1, v2, andTable), BOOLEAN, BOOLEAN, BOOLEAN)); } private static DefaultFunctionResolver or() { - return FunctionDSL.define(BuiltinFunctionName.OR.getName(), FunctionDSL - .impl((v1, v2) -> lookupTableFunction(v1, v2, orTable), BOOLEAN, BOOLEAN, - BOOLEAN)); + return FunctionDSL.define(BuiltinFunctionName.OR.getName(), + impl((v1, v2) -> lookupTableFunction(v1, v2, orTable), BOOLEAN, BOOLEAN, BOOLEAN)); } private static DefaultFunctionResolver xor() { - return FunctionDSL.define(BuiltinFunctionName.XOR.getName(), FunctionDSL - .impl((v1, v2) -> lookupTableFunction(v1, v2, xorTable), BOOLEAN, BOOLEAN, - BOOLEAN)); + return FunctionDSL.define(BuiltinFunctionName.XOR.getName(), + impl((v1, v2) -> lookupTableFunction(v1, v2, xorTable), BOOLEAN, BOOLEAN, BOOLEAN)); } private static DefaultFunctionResolver equal() { - return FunctionDSL.define(BuiltinFunctionName.EQUAL.getName(), - ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL.impl( - FunctionDSL.nullMissingHandling((v1, v2) -> ExprBooleanValue.of(v1.equals(v2))), - BOOLEAN, type, type)) - .collect( - Collectors.toList())); + return compareImpl(BuiltinFunctionName.EQUAL.getName(), + (Comparable v1, Comparable v2) -> v1.equals(v2)); } private static DefaultFunctionResolver notEqual() { - return FunctionDSL - .define(BuiltinFunctionName.NOTEQUAL.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl( - FunctionDSL - .nullMissingHandling((v1, v2) -> ExprBooleanValue.of(!v1.equals(v2))), - BOOLEAN, - type, - type)) - .collect( - Collectors.toList())); + return compareImpl(BuiltinFunctionName.NOTEQUAL.getName(), + (Comparable v1, Comparable v2) -> !v1.equals(v2)); } private static DefaultFunctionResolver less() { - return FunctionDSL - .define(BuiltinFunctionName.LESS.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl(FunctionDSL - .nullMissingHandling((v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) < 0)), - BOOLEAN, - type, type)) - .collect( - Collectors.toList())); + return compareImpl(BuiltinFunctionName.LESS.getName(), + (Comparable v1, Comparable v2) -> v1.compareTo(v2) < 0); } private static DefaultFunctionResolver lte() { - return FunctionDSL - .define(BuiltinFunctionName.LTE.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl( - FunctionDSL - .nullMissingHandling( - (v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) <= 0)), - BOOLEAN, - type, type)) - .collect( - Collectors.toList())); + return compareImpl(BuiltinFunctionName.LTE.getName(), + (Comparable v1, Comparable v2) -> v1.compareTo(v2) <= 0); } private static DefaultFunctionResolver greater() { - return FunctionDSL - .define(BuiltinFunctionName.GREATER.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl(FunctionDSL - .nullMissingHandling((v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) > 0)), - BOOLEAN, type, type)) - .collect( - Collectors.toList())); + return compareImpl(BuiltinFunctionName.GREATER.getName(), + (Comparable v1, Comparable v2) -> v1.compareTo(v2) > 0); } private static DefaultFunctionResolver gte() { - return FunctionDSL - .define(BuiltinFunctionName.GTE.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) >= 0)), - BOOLEAN, - type, type)) - .collect( - Collectors.toList())); + return compareImpl(BuiltinFunctionName.GTE.getName(), + (Comparable v1, Comparable v2) -> v1.compareTo(v2) >= 0); + } + + private static DefaultFunctionResolver compareImpl( + FunctionName function, SerializableBiFunction comparator) { + return FunctionDSL.define(function, + Stream.concat( + ExprCoreType.coreTypes().stream() + .map(type -> impl(nullMissingHandling( + (v1, v2) -> ExprBooleanValue.of(comparator.apply(v1, v2))), + BOOLEAN, type, type)), + permuteTemporalTypesByPairs().stream() + .map(pair -> implWithProperties(nullMissingHandlingWithProperties( + (fp, v1, v2) -> ExprBooleanValue.of(comparator.apply( + extractDateTime(v1, fp), extractDateTime(v2, fp)))), + BOOLEAN, pair.getLeft(), pair.getRight()))) + .collect(Collectors.toList())); } private static DefaultFunctionResolver like() { - return FunctionDSL.define(BuiltinFunctionName.LIKE.getName(), FunctionDSL - .impl(FunctionDSL.nullMissingHandling(OperatorUtils::matches), BOOLEAN, STRING, - STRING)); + return FunctionDSL.define(BuiltinFunctionName.LIKE.getName(), + impl(nullMissingHandling(OperatorUtils::matches), BOOLEAN, STRING, STRING)); } private static DefaultFunctionResolver regexp() { - return FunctionDSL.define(BuiltinFunctionName.REGEXP.getName(), FunctionDSL - .impl(FunctionDSL.nullMissingHandling(OperatorUtils::matchesRegexp), - INTEGER, STRING, STRING)); + return FunctionDSL.define(BuiltinFunctionName.REGEXP.getName(), + impl(nullMissingHandling(OperatorUtils::matchesRegexp), INTEGER, STRING, STRING)); } private static DefaultFunctionResolver notLike() { - return FunctionDSL.define(BuiltinFunctionName.NOT_LIKE.getName(), FunctionDSL - .impl(FunctionDSL.nullMissingHandling( + return FunctionDSL.define(BuiltinFunctionName.NOT_LIKE.getName(), impl(nullMissingHandling( (v1, v2) -> UnaryPredicateOperator.not(OperatorUtils.matches(v1, v2))), - BOOLEAN, - STRING, - STRING)); + BOOLEAN, STRING, STRING)); } private static ExprValue lookupTableFunction(ExprValue arg1, ExprValue arg2, @@ -261,4 +239,13 @@ private static ExprValue lookupTableFunction(ExprValue arg1, ExprValue arg2, return table.get(arg2, arg1); } } + + private static List> permuteTemporalTypesByPairs() { + return List.of( + Pair.of(DATE, TIME), Pair.of(DATE, DATETIME), Pair.of(DATE, TIMESTAMP), + Pair.of(TIME, DATE), Pair.of(TIME, DATETIME), Pair.of(TIME, TIMESTAMP), + Pair.of(DATETIME, TIME), Pair.of(DATETIME, DATE), Pair.of(DATETIME, TIMESTAMP), + Pair.of(TIMESTAMP, TIME), Pair.of(TIMESTAMP, DATE), Pair.of(TIMESTAMP, DATETIME) + ); + } } diff --git a/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java b/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java index 5a99af3f83..6ca9486de6 100644 --- a/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java +++ b/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java @@ -10,6 +10,9 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import lombok.experimental.UtilityClass; +import org.opensearch.sql.data.model.ExprTimeValue; +import org.opensearch.sql.data.model.ExprValue; +import org.opensearch.sql.expression.function.FunctionProperties; @UtilityClass public class DateTimeUtils { @@ -125,4 +128,15 @@ public Boolean isValidMySqlTimeZoneId(ZoneId zone) { && (passedTzValidator.isAfter(minTzValidator) || passedTzValidator.isEqual(minTzValidator)); } + + /** + * Extracts LocalDateTime from a datetime ExprValue. + * Uses `FunctionProperties` for `ExprTimeValue`. + */ + public static LocalDateTime extractDateTime(ExprValue value, + FunctionProperties functionProperties) { + return value instanceof ExprTimeValue + ? ((ExprTimeValue) value).datetimeValue(functionProperties) + : value.datetimeValue(); + } } diff --git a/core/src/test/java/org/opensearch/sql/data/model/DateTimeValueTest.java b/core/src/test/java/org/opensearch/sql/data/model/DateTimeValueTest.java index 3a7df17d90..a335478e19 100644 --- a/core/src/test/java/org/opensearch/sql/data/model/DateTimeValueTest.java +++ b/core/src/test/java/org/opensearch/sql/data/model/DateTimeValueTest.java @@ -15,11 +15,11 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneId; import java.time.ZonedDateTime; import org.junit.jupiter.api.Test; import org.opensearch.sql.exception.ExpressionEvaluationException; import org.opensearch.sql.exception.SemanticCheckException; +import org.opensearch.sql.expression.function.FunctionProperties; public class DateTimeValueTest { @@ -27,14 +27,33 @@ public class DateTimeValueTest { @Test public void timeValueInterfaceTest() { - ExprValue timeValue = new ExprTimeValue("01:01:01"); + ExprTimeValue timeValue = new ExprTimeValue("01:01:01"); assertEquals(TIME, timeValue.type()); + assertEquals(LocalTime.parse("01:01:01"), timeValue.timeValue()); + // It is prohibited to acquire values which include date part from `ExprTimeValue` + // without a FunctionProperties object + var exception = assertThrows(ExpressionEvaluationException.class, timeValue::dateValue); + assertEquals("invalid to get dateValue from value of type TIME", exception.getMessage()); + exception = assertThrows(ExpressionEvaluationException.class, timeValue::datetimeValue); + assertEquals("invalid to get datetimeValue from value of type TIME", exception.getMessage()); + exception = assertThrows(ExpressionEvaluationException.class, timeValue::timestampValue); + assertEquals("invalid to get timestampValue from value of type TIME", exception.getMessage()); + + var functionProperties = new FunctionProperties(); + var today = LocalDate.now(functionProperties.getQueryStartClock()); + + assertEquals(today, timeValue.dateValue(functionProperties)); + assertEquals(today.atTime(1, 1, 1), timeValue.datetimeValue(functionProperties)); + assertEquals(ZonedDateTime.of(LocalTime.parse("01:01:01").atDate(today), + ExprTimestampValue.ZONE).toInstant(), timeValue.timestampValue(functionProperties)); + assertEquals("01:01:01", timeValue.value()); assertEquals("TIME '01:01:01'", timeValue.toString()); - assertThrows(ExpressionEvaluationException.class, () -> integerValue(1).timeValue(), - "invalid to get timeValue from value of type INTEGER"); + exception = assertThrows(ExpressionEvaluationException.class, + () -> integerValue(1).timeValue()); + assertEquals("invalid to get timeValue from value of type INTEGER", exception.getMessage()); } @Test @@ -43,7 +62,7 @@ public void timestampValueInterfaceTest() { assertEquals(TIMESTAMP, timestampValue.type()); assertEquals(ZonedDateTime.of(LocalDateTime.parse("2020-07-07T01:01:01"), - ZoneId.of("UTC")).toInstant(), timestampValue.timestampValue()); + ExprTimestampValue.ZONE).toInstant(), timestampValue.timestampValue()); assertEquals("2020-07-07 01:01:01", timestampValue.value()); assertEquals("TIMESTAMP '2020-07-07 01:01:01'", timestampValue.toString()); assertEquals(LocalDate.parse("2020-07-07"), timestampValue.dateValue()); @@ -61,7 +80,7 @@ public void dateValueInterfaceTest() { assertEquals(LocalTime.parse("00:00:00"), dateValue.timeValue()); assertEquals(LocalDateTime.parse("2012-07-07T00:00:00"), dateValue.datetimeValue()); assertEquals(ZonedDateTime.of(LocalDateTime.parse("2012-07-07T00:00:00"), - ZoneId.systemDefault()).toInstant(), dateValue.timestampValue()); + ExprTimestampValue.ZONE).toInstant(), dateValue.timestampValue()); ExpressionEvaluationException exception = assertThrows(ExpressionEvaluationException.class, () -> integerValue(1).dateValue()); assertEquals("invalid to get dateValue from value of type INTEGER", @@ -76,7 +95,7 @@ public void datetimeValueInterfaceTest() { assertEquals(LocalDate.parse("2020-08-17"), datetimeValue.dateValue()); assertEquals(LocalTime.parse("19:44:00"), datetimeValue.timeValue()); assertEquals(ZonedDateTime.of(LocalDateTime.parse("2020-08-17T19:44:00"), - ZoneId.of("UTC")).toInstant(), datetimeValue.timestampValue()); + ExprTimestampValue.ZONE).toInstant(), datetimeValue.timestampValue()); assertEquals("DATETIME '2020-08-17 19:44:00'", datetimeValue.toString()); assertThrows(ExpressionEvaluationException.class, () -> integerValue(1).datetimeValue(), "invalid to get datetimeValue from value of type INTEGER"); diff --git a/core/src/test/java/org/opensearch/sql/data/model/ExprBooleanValueTest.java b/core/src/test/java/org/opensearch/sql/data/model/ExprBooleanValueTest.java index a2eda4419b..07aac33129 100644 --- a/core/src/test/java/org/opensearch/sql/data/model/ExprBooleanValueTest.java +++ b/core/src/test/java/org/opensearch/sql/data/model/ExprBooleanValueTest.java @@ -8,7 +8,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.opensearch.sql.utils.ComparisonUtil.compare; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN; import org.junit.jupiter.api.Test; import org.opensearch.sql.exception.ExpressionEvaluationException; @@ -16,10 +17,46 @@ public class ExprBooleanValueTest { @Test - public void comparabilityTest() { - ExprValue booleanValue = ExprValueUtils.booleanValue(false); - ExpressionEvaluationException exception = assertThrows(ExpressionEvaluationException.class, - () -> compare(booleanValue, booleanValue)); - assertEquals("ExprBooleanValue instances are not comparable", exception.getMessage()); + public void equals_to_self() { + ExprValue value = ExprValueUtils.booleanValue(false); + assertEquals(value.booleanValue(), false); + assertTrue(value.equals(value)); + } + + @Test + public void equal() { + ExprValue v1 = ExprBooleanValue.of(true); + ExprValue v2 = ExprBooleanValue.of(true); + assertTrue(v1.equals(v2)); + assertTrue(v2.equals(v1)); + assertEquals(0, ((ExprBooleanValue)v1).compare((ExprBooleanValue)v2)); + assertEquals(0, ((ExprBooleanValue)v2).compare((ExprBooleanValue)v1)); + } + + @Test + public void compare() { + var v1 = ExprBooleanValue.of(true); + var v2 = ExprBooleanValue.of(false); + assertEquals(1, v1.compare(v2)); + assertEquals(-1, v2.compare(v1)); + } + + @Test + public void invalid_get_value() { + ExprDateValue value = new ExprDateValue("2020-08-20"); + assertThrows(ExpressionEvaluationException.class, value::booleanValue, + String.format("invalid to get booleanValue from value of type %s", value.type())); + } + + @Test + public void value() { + ExprValue value = ExprBooleanValue.of(true); + assertEquals(true, value.value()); + } + + @Test + public void type() { + ExprValue value = ExprBooleanValue.of(false); + assertEquals(BOOLEAN, value.type()); } } diff --git a/core/src/test/java/org/opensearch/sql/data/model/ExprStringValueTest.java b/core/src/test/java/org/opensearch/sql/data/model/ExprStringValueTest.java new file mode 100644 index 0000000000..abbb730a0c --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/data/model/ExprStringValueTest.java @@ -0,0 +1,60 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.data.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.opensearch.sql.data.type.ExprCoreType.STRING; + +import org.junit.jupiter.api.Test; +import org.opensearch.sql.exception.ExpressionEvaluationException; + +public class ExprStringValueTest { + @Test + public void equals_to_self() { + ExprValue string = ExprValueUtils.stringValue("str"); + assertEquals(string.stringValue(), "str"); + assertTrue(string.equals(string)); + } + + @Test + public void equal() { + ExprValue v1 = new ExprStringValue("str"); + ExprValue v2 = ExprValueUtils.stringValue("str"); + assertTrue(v1.equals(v2)); + assertTrue(v2.equals(v1)); + assertEquals(0, ((ExprStringValue)v1).compare((ExprStringValue)v2)); + assertEquals(0, ((ExprStringValue)v2).compare((ExprStringValue)v1)); + } + + @Test + public void compare() { + ExprStringValue v1 = new ExprStringValue("str1"); + ExprStringValue v2 = new ExprStringValue("str2"); + assertEquals(-1, v1.compare(v2)); + assertEquals(1, v2.compare(v1)); + } + + @Test + public void invalid_get_value() { + ExprDateValue value = new ExprDateValue("2020-08-20"); + assertThrows(ExpressionEvaluationException.class, value::stringValue, + String.format("invalid to get intervalValue from value of type %s", value.type())); + } + + @Test + public void value() { + ExprValue value = new ExprStringValue("string"); + assertEquals("string", value.value()); + } + + @Test + public void type() { + ExprValue value = new ExprStringValue("string"); + assertEquals(STRING, value.type()); + } +} diff --git a/core/src/test/java/org/opensearch/sql/data/model/ExprValueCompareTest.java b/core/src/test/java/org/opensearch/sql/data/model/ExprValueCompareTest.java index e2eec475ae..3ece5e9a96 100644 --- a/core/src/test/java/org/opensearch/sql/data/model/ExprValueCompareTest.java +++ b/core/src/test/java/org/opensearch/sql/data/model/ExprValueCompareTest.java @@ -7,14 +7,24 @@ package org.opensearch.sql.data.model; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_FALSE; import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_MISSING; import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_NULL; +import static org.opensearch.sql.utils.DateTimeUtils.extractDateTime; +import java.time.LocalDate; +import java.time.Period; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.opensearch.sql.exception.ExpressionEvaluationException; +import org.opensearch.sql.expression.ExpressionTestBase; -public class ExprValueCompareTest { +public class ExprValueCompareTest extends ExpressionTestBase { @Test public void timeValueCompare() { @@ -56,6 +66,179 @@ public void timestampValueCompare() { .compareTo(new ExprTimestampValue("2012-08-07 19:00:00"))); } + private static Stream getEqualDatetimeValuesOfDifferentTypes() { + return Stream.of( + Arguments.of(new ExprTimestampValue("1961-04-12 09:07:00"), + new ExprDatetimeValue("1961-04-12 09:07:00")), + Arguments.of(new ExprTimestampValue("1984-11-22 00:00:00"), + new ExprDateValue("1984-11-22")), + Arguments.of(new ExprTimestampValue(LocalDate.now() + " 00:00:00"), + new ExprDateValue(LocalDate.now())), + Arguments.of(new ExprDatetimeValue(LocalDate.now() + " 17:42:15"), + new ExprTimeValue("17:42:15")), + Arguments.of(new ExprDatetimeValue("2012-08-07 19:14:38"), + new ExprTimestampValue("2012-08-07 19:14:38")), + Arguments.of(new ExprDateValue("2012-08-07"), + new ExprDatetimeValue("2012-08-07 00:00:00")), + Arguments.of(new ExprDateValue("2007-01-27"), + new ExprDatetimeValue("2007-01-27 00:00:00")), + Arguments.of(new ExprDateValue(LocalDate.now()), + new ExprTimeValue("00:00:00")), + Arguments.of(new ExprTimestampValue("1984-11-22 00:00:00"), + new ExprDateValue("1984-11-22")), + Arguments.of(new ExprTimeValue("19:14:38"), + new ExprDatetimeValue(LocalDate.now() + " 19:14:38")), + Arguments.of(new ExprTimeValue("17:42:15"), + new ExprTimestampValue(LocalDate.now() + " 17:42:15")) + ); + } + + /** + * We can't compare directly ExprValues of different datetime types, we need to use + * `FunctionProperties` object to extract comparable values. + */ + @ParameterizedTest + @MethodSource("getEqualDatetimeValuesOfDifferentTypes") + public void compareEqDifferentDateTimeValueTypes(ExprValue left, ExprValue right) { + assertEquals(0, extractDateTime(left, functionProperties) + .compareTo(extractDateTime(right, functionProperties))); + assertEquals(0, extractDateTime(right, functionProperties) + .compareTo(extractDateTime(left, functionProperties))); + } + + private static Stream getNotEqualDatetimeValuesOfDifferentTypes() { + return Stream.of( + Arguments.of(new ExprDatetimeValue("2012-08-07 19:14:38"), + new ExprTimestampValue("1961-04-12 09:07:00")), + Arguments.of(new ExprDatetimeValue("2012-08-07 19:14:38"), + new ExprTimeValue("09:07:00")), + Arguments.of(new ExprDatetimeValue(LocalDate.now() + " 19:14:38"), + new ExprTimeValue("09:07:00")), + Arguments.of(new ExprDatetimeValue("2012-08-07 00:00:00"), + new ExprDateValue("1961-04-12")), + Arguments.of(new ExprDatetimeValue("1961-04-12 19:14:38"), + new ExprDateValue("1961-04-12")), + Arguments.of(new ExprDateValue("1984-11-22"), + new ExprDatetimeValue("1961-04-12 19:14:38")), + Arguments.of(new ExprDateValue("1984-11-22"), + new ExprTimestampValue("2020-09-16 17:30:00")), + Arguments.of(new ExprDateValue("1984-11-22"), + new ExprTimeValue("19:14:38")), + Arguments.of(new ExprTimeValue("19:14:38"), + new ExprDateValue(LocalDate.now())), + Arguments.of(new ExprTimeValue("19:14:38"), + new ExprDatetimeValue("2012-08-07 09:07:00")), + Arguments.of(new ExprTimeValue("19:14:38"), + new ExprTimestampValue("1984-02-03 04:05:07")), + Arguments.of(new ExprTimestampValue("2012-08-07 19:14:38"), + new ExprDatetimeValue("1961-04-12 09:07:00")), + Arguments.of(new ExprTimestampValue("2012-08-07 19:14:38"), + new ExprTimeValue("09:07:00")), + Arguments.of(new ExprTimestampValue(LocalDate.now() + " 19:14:38"), + new ExprTimeValue("09:07:00")), + Arguments.of(new ExprTimestampValue("2012-08-07 00:00:00"), + new ExprDateValue("1961-04-12")), + Arguments.of(new ExprTimestampValue("1961-04-12 19:14:38"), + new ExprDateValue("1961-04-12")) + ); + } + + /** + * We can't compare directly ExprValues of different datetime types, we need to use + * `FunctionProperties` object to extract comparable values. + */ + @ParameterizedTest + @MethodSource("getNotEqualDatetimeValuesOfDifferentTypes") + public void compareNeqDifferentDateTimeValueTypes(ExprValue left, ExprValue right) { + assertNotEquals(0, extractDateTime(left, functionProperties) + .compareTo(extractDateTime(right, functionProperties))); + assertNotEquals(0, extractDateTime(right, functionProperties) + .compareTo(extractDateTime(left, functionProperties))); + } + + @Test + public void compareDateTimeWithNotADateTime() { + var exception = assertThrows(ExpressionEvaluationException.class, () -> + new ExprDoubleValue(3.1415).compareTo(new ExprIntervalValue(Period.ofDays(1)))); + assertEquals("compare expected value have same type, but with [DOUBLE, INTERVAL]", + exception.getMessage()); + + exception = assertThrows(ExpressionEvaluationException.class, () -> + new ExprDateValue("1961-04-12").compareTo(new ExprIntegerValue(1))); + assertEquals("compare expected value have same type, but with [DATE, INTEGER]", + exception.getMessage()); + + exception = assertThrows(ExpressionEvaluationException.class, () -> + new ExprStringValue("something").compareTo(new ExprTimeValue("10:20:30"))); + assertEquals("compare expected value have same type, but with [STRING, TIME]", + exception.getMessage()); + } + + @Test + public void intValueCompare() { + assertEquals(0, new ExprIntegerValue(1).compareTo(new ExprIntegerValue(1))); + assertEquals(1, new ExprIntegerValue(2).compareTo(new ExprIntegerValue(1))); + assertEquals(-1, new ExprIntegerValue(1).compareTo(new ExprIntegerValue(2))); + } + + @Test + public void doubleValueCompare() { + assertEquals(0, new ExprDoubleValue(1).compareTo(new ExprDoubleValue(1))); + assertEquals(1, new ExprDoubleValue(2).compareTo(new ExprDoubleValue(1))); + assertEquals(-1, new ExprDoubleValue(1).compareTo(new ExprDoubleValue(2))); + } + + private static Stream getEqualNumericValuesOfDifferentTypes() { + return Stream.of( + Arguments.of(new ExprIntegerValue(42), new ExprByteValue(42)), + Arguments.of(new ExprIntegerValue(42), new ExprShortValue(42)), + Arguments.of(new ExprIntegerValue(42), new ExprLongValue(42)), + Arguments.of(new ExprIntegerValue(42), new ExprFloatValue(42)), + Arguments.of(new ExprIntegerValue(42), new ExprDoubleValue(42)) + ); + } + + @ParameterizedTest + @MethodSource("getEqualNumericValuesOfDifferentTypes") + public void compareEqDifferentNumericValueTypes(ExprValue left, ExprValue right) { + assertEquals(0, left.compareTo(right)); + assertEquals(0, right.compareTo(left)); + } + + private static Stream getNotEqualNumericValuesOfDifferentTypes() { + return Stream.of( + Arguments.of(new ExprIntegerValue(42), new ExprByteValue(1)), + Arguments.of(new ExprIntegerValue(42), new ExprShortValue(146)), + Arguments.of(new ExprIntegerValue(42), new ExprLongValue(100500)), + Arguments.of(new ExprIntegerValue(42), new ExprFloatValue(-1.5)), + Arguments.of(new ExprIntegerValue(42), new ExprDoubleValue(1468.84138)) + ); + } + + @ParameterizedTest + @MethodSource("getNotEqualNumericValuesOfDifferentTypes") + public void compareNeqDifferentNumericValueTypes(ExprValue left, ExprValue right) { + assertNotEquals(0, left.compareTo(right)); + assertNotEquals(0, right.compareTo(left)); + } + + @Test + public void stringValueCompare() { + assertEquals(0, new ExprStringValue("str1").compareTo(new ExprStringValue("str1"))); + assertEquals(1, new ExprStringValue("str2").compareTo(new ExprStringValue("str1"))); + assertEquals(-1, new ExprStringValue("str1").compareTo(new ExprStringValue("str2"))); + } + + @Test + public void intervalValueCompare() { + assertEquals(0, new ExprIntervalValue(Period.ofDays(1)) + .compareTo(new ExprIntervalValue(Period.ofDays(1)))); + assertEquals(1, new ExprIntervalValue(Period.ofDays(2)) + .compareTo(new ExprIntervalValue(Period.ofDays(1)))); + assertEquals(-1, new ExprIntervalValue(Period.ofDays(1)) + .compareTo(new ExprIntervalValue(Period.ofDays(2)))); + } + @Test public void missingCompareToMethodShouldNotBeenCalledDirectly() { IllegalStateException exception = assertThrows(IllegalStateException.class, diff --git a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLTestBase.java b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLTestBase.java index 193066e626..63c6ea3329 100644 --- a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLTestBase.java +++ b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLTestBase.java @@ -52,6 +52,8 @@ public int compareTo(ExprValue o) { static final SerializableFunction oneArg = v -> ANY; static final SerializableBiFunction oneArgWithProperties = (functionProperties, v) -> ANY; + static final SerializableTriFunction + twoArgWithProperties = (functionProperties, v1, v2) -> ANY; static final SerializableBiFunction twoArgs = (v1, v2) -> ANY; diff --git a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgTest.java b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgTest.java new file mode 100644 index 0000000000..18444a476e --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgTest.java @@ -0,0 +1,33 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.expression.function; + +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.opensearch.sql.data.model.ExprValue; +import org.opensearch.sql.expression.DSL; +import org.opensearch.sql.expression.Expression; + +class FunctionDSLimplWithPropertiesTwoArgTest extends FunctionDSLimplTestBase { + + @Override + SerializableFunction> + getImplementationGenerator() { + SerializableTriFunction functionBody + = (fp, arg1, arg2) -> ANY; + return FunctionDSL.implWithProperties(functionBody, ANY_TYPE, ANY_TYPE, ANY_TYPE); + } + + @Override + List getSampleArguments() { + return List.of(DSL.literal(ANY), DSL.literal(ANY)); + } + + @Override + String getExpected_toString() { + return "sample(ANY, ANY)"; + } +} diff --git a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLnullMissingHandlingTest.java b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLnullMissingHandlingTest.java index 64cac278f6..17f1de355f 100644 --- a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLnullMissingHandlingTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLnullMissingHandlingTest.java @@ -47,6 +47,41 @@ void nullMissingHandling_oneArg_FunctionProperties_apply() { nullMissingHandlingWithProperties(oneArgWithProperties).apply(functionProperties, ANY)); } + @Test + void nullMissingHandling_twoArgs_FunctionProperties_nullValue_firstArg() { + assertEquals(NULL, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, NULL, ANY)); + } + + @Test + void nullMissingHandling_twoArgs_FunctionProperties_nullValue_secondArg() { + assertEquals(NULL, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, ANY, NULL)); + } + + @Test + void nullMissingHandling_twoArgs_FunctionProperties_missingValue_firstArg() { + assertEquals(MISSING, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, MISSING, ANY)); + } + + @Test + void nullMissingHandling_twoArgs_FunctionProperties_missingValue_secondArg() { + assertEquals(MISSING, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, ANY, MISSING)); + } + + @Test + void nullMissingHandling_twoArgs_FunctionProperties_apply() { + assertEquals(ANY, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, ANY, ANY)); + } + @Test void nullMissingHandling_twoArgs_firstArg_nullValue() { assertEquals(NULL, nullMissingHandling(twoArgs).apply(NULL, ANY)); diff --git a/core/src/test/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperatorTest.java b/core/src/test/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperatorTest.java index 7354b52e24..e2c1bf9b9a 100644 --- a/core/src/test/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperatorTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperatorTest.java @@ -21,9 +21,11 @@ import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_TRUE; import static org.opensearch.sql.data.model.ExprValueUtils.booleanValue; import static org.opensearch.sql.data.model.ExprValueUtils.fromObjectValue; +import static org.opensearch.sql.data.type.ExprCoreType.ARRAY; import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN; import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; import static org.opensearch.sql.data.type.ExprCoreType.STRING; +import static org.opensearch.sql.data.type.ExprCoreType.STRUCT; import static org.opensearch.sql.utils.ComparisonUtil.compare; import static org.opensearch.sql.utils.OperatorUtils.matches; @@ -34,6 +36,11 @@ import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; import java.util.Arrays; import java.util.Base64; import java.util.List; @@ -44,16 +51,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.opensearch.sql.data.model.ExprBooleanValue; -import org.opensearch.sql.data.model.ExprByteValue; -import org.opensearch.sql.data.model.ExprCollectionValue; -import org.opensearch.sql.data.model.ExprDoubleValue; -import org.opensearch.sql.data.model.ExprFloatValue; -import org.opensearch.sql.data.model.ExprIntegerValue; -import org.opensearch.sql.data.model.ExprLongValue; -import org.opensearch.sql.data.model.ExprShortValue; import org.opensearch.sql.data.model.ExprStringValue; -import org.opensearch.sql.data.model.ExprTupleValue; import org.opensearch.sql.data.model.ExprValue; import org.opensearch.sql.data.model.ExprValueUtils; import org.opensearch.sql.expression.DSL; @@ -87,54 +85,88 @@ private static Stream binaryPredicateArguments() { .map(list -> Arguments.of(list.get(0), list.get(1))); } + private static List> getValuesForComparisonTests() { + return List.of( + List.of(1, 2), + List.of((byte) 1, (byte) 2), + List.of((short) 1, (short) 2), + List.of(1L, 2L), + List.of(1F, 2F), + List.of(1D, 2D), + List.of("str", "str0"), + List.of(true, false), + List.of(LocalTime.of(9, 7, 0), LocalTime.of(7, 40, 0)), + List.of(LocalDate.of(1961, 4, 12), LocalDate.of(1984, 10, 25)), + List.of(Instant.ofEpochSecond(42), Instant.ofEpochSecond(100500)), + List.of(LocalDateTime.of(1961, 4, 12, 9, 7, 0), LocalDateTime.of(1984, 10, 25, 7, 40)), + List.of(LocalDate.of(1961, 4, 12), LocalTime.now().minusHours(1)), + List.of(LocalDate.of(1961, 4, 12), LocalDateTime.of(1984, 10, 25, 7, 40)), + List.of(Instant.ofEpochSecond(100500), LocalDate.of(1961, 4, 12)), + List.of(Instant.ofEpochSecond(100500), LocalTime.of(7, 40, 0)), + List.of(LocalTime.of(7, 40, 0), LocalDateTime.of(1984, 10, 25, 7, 40)), + List.of(Instant.ofEpochSecond(42), LocalDateTime.of(1984, 10, 25, 7, 40)) + ); + } + private static Stream testEqualArguments() { Stream.Builder builder = Stream.builder(); - builder.add(Arguments.of(new ExprByteValue(1), new ExprByteValue(1))); - builder.add(Arguments.of(new ExprShortValue(1), new ExprShortValue(1))); - builder.add(Arguments.of(new ExprIntegerValue(1), new ExprIntegerValue(1))); - builder.add(Arguments.of(new ExprLongValue(1L), new ExprLongValue(1L))); - builder.add(Arguments.of(new ExprFloatValue(1F), new ExprFloatValue(1F))); - builder.add(Arguments.of(new ExprDoubleValue(1D), new ExprDoubleValue(1D))); - builder.add(Arguments.of(new ExprStringValue("str"), new ExprStringValue("str"))); - builder.add(Arguments.of(ExprBooleanValue.of(true), ExprBooleanValue.of(true))); - builder.add(Arguments.of(new ExprCollectionValue(ImmutableList.of(new ExprIntegerValue(1))), - new ExprCollectionValue(ImmutableList.of(new ExprIntegerValue(1))))); - builder.add(Arguments.of(ExprTupleValue.fromExprValueMap(ImmutableMap.of("str", - new ExprIntegerValue(1))), - ExprTupleValue.fromExprValueMap(ImmutableMap.of("str", new ExprIntegerValue(1))))); + for (List argPair : getValuesForComparisonTests()) { + builder.add(Arguments.of(fromObjectValue(argPair.get(0)), fromObjectValue(argPair.get(0)))); + builder.add(Arguments.of(fromObjectValue(argPair.get(1)), fromObjectValue(argPair.get(1)))); + } + builder.add(Arguments.of(fromObjectValue(LocalTime.of(7, 40, 0)), + fromObjectValue(LocalTime.of(7, 40, 0).atDate(LocalDate.now())))); + builder.add(Arguments.of(fromObjectValue(LocalDateTime.of(1970, 1, 1, 0, 0, 42)), + fromObjectValue(Instant.ofEpochSecond(42)))); + builder.add(Arguments.of(fromObjectValue(LocalDate.of(1970, 1, 1)), + fromObjectValue(Instant.ofEpochSecond(0)))); + builder.add(Arguments.of(fromObjectValue(LocalDate.of(1984, 10, 25)), + fromObjectValue(LocalDateTime.of(1984, 10, 25, 0, 0)))); + builder.add(Arguments.of(fromObjectValue(LocalTime.of(0, 0, 0)), + fromObjectValue(LocalDate.now()))); + builder.add(Arguments.of(fromObjectValue(LocalTime.of(0, 0, 0)), + fromObjectValue(LocalDate.now().atStartOfDay(ZoneId.of("UTC")).toInstant()))); + builder.add(Arguments.of(fromObjectValue(ImmutableList.of(1)), + fromObjectValue(ImmutableList.of(1)))); + builder.add(Arguments.of(fromObjectValue(ImmutableMap.of("str", 1)), + fromObjectValue(ImmutableMap.of("str", 1)))); return builder.build(); } private static Stream testNotEqualArguments() { - List> arguments = Arrays.asList( - Arrays.asList((byte) 1, (byte) 2), Arrays.asList(1, 2), Arrays.asList(1L, 2L), - Arrays.asList(1F, 2F), Arrays.asList(1D, 2D), - Arrays.asList("str0", "str1"), Arrays.asList(true, false), - Arrays.asList(ImmutableList.of(1), ImmutableList.of(2)), - Arrays.asList(ImmutableMap.of("str", 1), ImmutableMap.of("str", 2)) - ); Stream.Builder builder = Stream.builder(); - for (List argPair : arguments) { + for (List argPair : getValuesForComparisonTests()) { builder.add(Arguments.of(fromObjectValue(argPair.get(0)), fromObjectValue(argPair.get(1)))); + builder.add(Arguments.of(fromObjectValue(argPair.get(1)), fromObjectValue(argPair.get(0)))); } + builder.add(Arguments.of(fromObjectValue(LocalTime.of(7, 40, 0)), + fromObjectValue(LocalDateTime.of(1984, 10, 25, 7, 40, 0)))); + builder.add(Arguments.of(fromObjectValue(LocalDateTime.of(1984, 10, 25, 7, 40, 0)), + fromObjectValue(Instant.ofEpochSecond(42)))); + builder.add(Arguments.of(fromObjectValue(LocalDate.of(1984, 10, 25)), + fromObjectValue(Instant.ofEpochSecond(42)))); + builder.add(Arguments.of(fromObjectValue(LocalTime.of(7, 40, 0)), + fromObjectValue(Instant.ofEpochSecond(42)))); + builder.add(Arguments.of(fromObjectValue(LocalDate.of(1984, 10, 25)), + fromObjectValue(LocalDateTime.of(1984, 10, 25, 7, 40)))); + builder.add(Arguments.of(fromObjectValue(LocalDate.of(1984, 10, 25)), + fromObjectValue(LocalTime.of(7, 40, 0)))); + builder.add(Arguments.of(fromObjectValue(ImmutableList.of(1)), + fromObjectValue(ImmutableList.of(1, 2)))); + builder.add(Arguments.of(fromObjectValue(ImmutableList.of(1)), + fromObjectValue(ImmutableList.of(2)))); + builder.add(Arguments.of(fromObjectValue(ImmutableMap.of("str", 1)), + fromObjectValue(ImmutableMap.of("str2", 2)))); return builder.build(); } private static Stream testCompareValueArguments() { - List> arguments = Arrays.asList( - Arrays.asList(1, 1), Arrays.asList(1, 2), Arrays.asList(2, 1), - Arrays.asList(1L, 1L), Arrays.asList(1L, 2L), Arrays.asList(2L, 1L), - Arrays.asList(1F, 1F), Arrays.asList(1F, 2F), Arrays.asList(2F, 1F), - Arrays.asList(1D, 1D), Arrays.asList(1D, 2D), Arrays.asList(2D, 1D), - Arrays.asList("str", "str"), Arrays.asList("str", "str0"), Arrays.asList("str0", "str") - ); Stream.Builder builder = Stream.builder(); - for (List argPair : arguments) { + for (List argPair : getValuesForComparisonTests()) { + builder.add(Arguments.of(fromObjectValue(argPair.get(0)), fromObjectValue(argPair.get(0)))); builder.add(Arguments.of(fromObjectValue(argPair.get(0)), fromObjectValue(argPair.get(1)))); + builder.add(Arguments.of(fromObjectValue(argPair.get(1)), fromObjectValue(argPair.get(0)))); } - builder.add(Arguments.of(new ExprShortValue(1), new ExprShortValue(1))); - builder.add(Arguments.of(new ExprShortValue(1), new ExprShortValue(2))); - builder.add(Arguments.of(new ExprShortValue(2), new ExprShortValue(1))); return builder.build(); } @@ -377,10 +409,16 @@ public void test_null_xor_missing() { @ParameterizedTest(name = "equal({0}, {1})") @MethodSource("testEqualArguments") public void test_equal(ExprValue v1, ExprValue v2) { - FunctionExpression equal = DSL.equal(DSL.literal(v1), DSL.literal(v2)); + FunctionExpression equal = DSL.equal(functionProperties, DSL.literal(v1), DSL.literal(v2)); assertEquals(BOOLEAN, equal.type()); - assertEquals(v1.value().equals(v2.value()), - ExprValueUtils.getBooleanValue(equal.valueOf(valueEnv()))); + if (v1.type() == v2.type()) { + assertEquals(v1.value().equals(v2.value()), + ExprValueUtils.getBooleanValue(equal.valueOf(valueEnv()))); + } + if (v1.type() != STRUCT && v1.type() != ARRAY) { + assertEquals(0 == compare(functionProperties, v1, v2), + ExprValueUtils.getBooleanValue(equal.valueOf(valueEnv()))); + } assertEquals(String.format("=(%s, %s)", v1.toString(), v2.toString()), equal.toString()); } @@ -426,10 +464,17 @@ public void test_null_equal_missing() { @ParameterizedTest(name = "equal({0}, {1})") @MethodSource({"testEqualArguments", "testNotEqualArguments"}) public void test_notequal(ExprValue v1, ExprValue v2) { - FunctionExpression notequal = DSL.notequal(DSL.literal(v1), DSL.literal(v2)); + FunctionExpression notequal = DSL.notequal(functionProperties, + DSL.literal(v1), DSL.literal(v2)); assertEquals(BOOLEAN, notequal.type()); - assertEquals(!v1.value().equals(v2.value()), - ExprValueUtils.getBooleanValue(notequal.valueOf(valueEnv()))); + if (v1.type() == v2.type()) { + assertEquals(!v1.value().equals(v2.value()), + ExprValueUtils.getBooleanValue(notequal.valueOf(valueEnv()))); + } + if (v1.type() != STRUCT && v1.type() != ARRAY) { + assertEquals(0 != compare(functionProperties, v1, v2), + ExprValueUtils.getBooleanValue(notequal.valueOf(valueEnv()))); + } assertEquals(String.format("!=(%s, %s)", v1.toString(), v2.toString()), notequal.toString()); } @@ -479,9 +524,9 @@ public void test_null_notequal_missing() { @ParameterizedTest(name = "less({0}, {1})") @MethodSource("testCompareValueArguments") public void test_less(ExprValue v1, ExprValue v2) { - FunctionExpression less = DSL.less(DSL.literal(v1), DSL.literal(v2)); + FunctionExpression less = DSL.less(functionProperties, DSL.literal(v1), DSL.literal(v2)); assertEquals(BOOLEAN, less.type()); - assertEquals(compare(v1, v2) < 0, + assertEquals(compare(functionProperties, v1, v2) < 0, ExprValueUtils.getBooleanValue(less.valueOf(valueEnv()))); assertEquals(String.format("<(%s, %s)", v1.toString(), v2.toString()), less.toString()); } @@ -536,9 +581,9 @@ public void test_null_less_missing() { @ParameterizedTest(name = "lte({0}, {1})") @MethodSource("testCompareValueArguments") public void test_lte(ExprValue v1, ExprValue v2) { - FunctionExpression lte = DSL.lte(DSL.literal(v1), DSL.literal(v2)); + FunctionExpression lte = DSL.lte(functionProperties, DSL.literal(v1), DSL.literal(v2)); assertEquals(BOOLEAN, lte.type()); - assertEquals(compare(v1, v2) <= 0, + assertEquals(compare(functionProperties, v1, v2) <= 0, ExprValueUtils.getBooleanValue(lte.valueOf(valueEnv()))); assertEquals(String.format("<=(%s, %s)", v1.toString(), v2.toString()), lte.toString()); } @@ -593,9 +638,9 @@ public void test_null_lte_missing() { @ParameterizedTest(name = "greater({0}, {1})") @MethodSource("testCompareValueArguments") public void test_greater(ExprValue v1, ExprValue v2) { - FunctionExpression greater = DSL.greater(DSL.literal(v1), DSL.literal(v2)); + FunctionExpression greater = DSL.greater(functionProperties, DSL.literal(v1), DSL.literal(v2)); assertEquals(BOOLEAN, greater.type()); - assertEquals(compare(v1, v2) > 0, + assertEquals(compare(functionProperties, v1, v2) > 0, ExprValueUtils.getBooleanValue(greater.valueOf(valueEnv()))); assertEquals(String.format(">(%s, %s)", v1.toString(), v2.toString()), greater.toString()); } @@ -650,9 +695,9 @@ public void test_null_greater_missing() { @ParameterizedTest(name = "gte({0}, {1})") @MethodSource("testCompareValueArguments") public void test_gte(ExprValue v1, ExprValue v2) { - FunctionExpression gte = DSL.gte(DSL.literal(v1), DSL.literal(v2)); + FunctionExpression gte = DSL.gte(functionProperties, DSL.literal(v1), DSL.literal(v2)); assertEquals(BOOLEAN, gte.type()); - assertEquals(compare(v1, v2) >= 0, + assertEquals(compare(functionProperties, v1, v2) >= 0, ExprValueUtils.getBooleanValue(gte.valueOf(valueEnv()))); assertEquals(String.format(">=(%s, %s)", v1.toString(), v2.toString()), gte.toString()); } diff --git a/core/src/test/java/org/opensearch/sql/utils/ComparisonUtil.java b/core/src/test/java/org/opensearch/sql/utils/ComparisonUtil.java index 9b2f8a0573..d6f0ef02cd 100644 --- a/core/src/test/java/org/opensearch/sql/utils/ComparisonUtil.java +++ b/core/src/test/java/org/opensearch/sql/utils/ComparisonUtil.java @@ -11,45 +11,58 @@ import static org.opensearch.sql.data.model.ExprValueUtils.getIntegerValue; import static org.opensearch.sql.data.model.ExprValueUtils.getLongValue; import static org.opensearch.sql.data.model.ExprValueUtils.getStringValue; +import static org.opensearch.sql.utils.DateTimeUtils.extractDateTime; -import org.opensearch.sql.data.model.ExprByteValue; -import org.opensearch.sql.data.model.ExprDoubleValue; -import org.opensearch.sql.data.model.ExprFloatValue; -import org.opensearch.sql.data.model.ExprIntegerValue; -import org.opensearch.sql.data.model.ExprLongValue; -import org.opensearch.sql.data.model.ExprShortValue; -import org.opensearch.sql.data.model.ExprStringValue; import org.opensearch.sql.data.model.ExprValue; +import org.opensearch.sql.data.type.ExprCoreType; import org.opensearch.sql.exception.ExpressionEvaluationException; +import org.opensearch.sql.expression.function.FunctionProperties; public class ComparisonUtil { + /** * Util to compare the object (integer, long, float, double, string) values. - * ExprValue A + * Allows comparing different datetime types and requires `FunctionProperties` object for that. */ - public static int compare(ExprValue v1, ExprValue v2) { + public static int compare(FunctionProperties functionProperties, ExprValue v1, ExprValue v2) { if (v1.isMissing() || v2.isMissing()) { throw new ExpressionEvaluationException("invalid to call compare operation on missing value"); } else if (v1.isNull() || v2.isNull()) { throw new ExpressionEvaluationException("invalid to call compare operation on null value"); + } else if (v1.type() != v2.type() && v1.isDateTime() && v2.isDateTime()) { + return extractDateTime(v1, functionProperties) + .compareTo(extractDateTime(v2, functionProperties)); } + return compare(v1, v2); + } - if (v1 instanceof ExprByteValue) { - return v1.byteValue().compareTo(v2.byteValue()); - } else if (v1 instanceof ExprShortValue) { - return v1.shortValue().compareTo(v2.shortValue()); - } else if (v1 instanceof ExprIntegerValue) { - return getIntegerValue(v1).compareTo(getIntegerValue(v2)); - } else if (v1 instanceof ExprLongValue) { - return getLongValue(v1).compareTo(getLongValue(v2)); - } else if (v1 instanceof ExprFloatValue) { - return getFloatValue(v1).compareTo(getFloatValue(v2)); - } else if (v1 instanceof ExprDoubleValue) { - return getDoubleValue(v1).compareTo(getDoubleValue(v2)); - } else if (v1 instanceof ExprStringValue) { - return getStringValue(v1).compareTo(getStringValue(v2)); - } else { + /** + * Util to compare the object (integer, long, float, double, string) values. + */ + public static int compare(ExprValue v1, ExprValue v2) { + if (v1.isMissing() || v2.isMissing()) { + throw new ExpressionEvaluationException("invalid to call compare operation on missing value"); + } else if (v1.isNull() || v2.isNull()) { + throw new ExpressionEvaluationException("invalid to call compare operation on null value"); + } else if (v1.type() != v2.type()) { throw new ExpressionEvaluationException( + "invalid to call compare operation on values of different types"); + } + + switch ((ExprCoreType)v1.type()) { + case BYTE: return v1.byteValue().compareTo(v2.byteValue()); + case SHORT: return v1.shortValue().compareTo(v2.shortValue()); + case INTEGER: return getIntegerValue(v1).compareTo(getIntegerValue(v2)); + case LONG: return getLongValue(v1).compareTo(getLongValue(v2)); + case FLOAT: return getFloatValue(v1).compareTo(getFloatValue(v2)); + case DOUBLE: return getDoubleValue(v1).compareTo(getDoubleValue(v2)); + case STRING: return getStringValue(v1).compareTo(getStringValue(v2)); + case BOOLEAN: return v1.booleanValue().compareTo(v2.booleanValue()); + case TIME: return v1.timeValue().compareTo(v2.timeValue()); + case DATE: return v1.dateValue().compareTo(v2.dateValue()); + case DATETIME: return v1.datetimeValue().compareTo(v2.datetimeValue()); + case TIMESTAMP: return v1.timestampValue().compareTo(v2.timestampValue()); + default: throw new ExpressionEvaluationException( String.format("%s instances are not comparable", v1.getClass().getSimpleName())); } } diff --git a/docs/user/dql/expressions.rst b/docs/user/dql/expressions.rst index a167ce29b5..dd27e94fe0 100644 --- a/docs/user/dql/expressions.rst +++ b/docs/user/dql/expressions.rst @@ -146,6 +146,10 @@ Here is an example for different type of comparison operators:: | True | True | False | True | False | False | +---------+----------+---------+----------+----------+---------+ +It is possible to compare datetimes. When comparing different datetime types, for example `DATE` and `TIME`, both converted to `DATETIME`. +The following rule is applied on coversion: a `TIME` applied to today's date; `DATE` is interpreted at midnight. + + LIKE ---- diff --git a/docs/user/ppl/functions/expressions.rst b/docs/user/ppl/functions/expressions.rst index c69252bc94..ac48324680 100644 --- a/docs/user/ppl/functions/expressions.rst +++ b/docs/user/ppl/functions/expressions.rst @@ -95,6 +95,9 @@ Operators | NOT | NOT NULL value test | +----------------+----------------------------------------+ +It is possible to compare datetimes. When comparing different datetime types, for example `DATE` and `TIME`, both converted to `DATETIME`. +The following rule is applied on coversion: a `TIME` applied to today's date; `DATE` is interpreted at midnight. + Examples -------- diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeComparisonIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeComparisonIT.java new file mode 100644 index 0000000000..b795977e7d --- /dev/null +++ b/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeComparisonIT.java @@ -0,0 +1,607 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.ppl; + +import static com.carrotsearch.randomizedtesting.RandomizedTest.$; +import static com.carrotsearch.randomizedtesting.RandomizedTest.$$; +import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATATYPE_NONNUMERIC; +import static org.opensearch.sql.util.MatcherUtils.rows; +import static org.opensearch.sql.util.MatcherUtils.schema; +import static org.opensearch.sql.util.MatcherUtils.verifyDataRows; +import static org.opensearch.sql.util.MatcherUtils.verifySchema; + +import java.io.IOException; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.TimeZone; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.jupiter.api.Test; + +public class DateTimeComparisonIT extends PPLIntegTestCase { + + @Override + public void init() throws IOException { + loadIndex(Index.DATA_TYPE_NONNUMERIC); + } + + private final TimeZone testTz = TimeZone.getDefault(); + private final TimeZone systemTz = TimeZone.getTimeZone(System.getProperty("user.timezone")); + + @Before + public void setTimeZone() { + TimeZone.setDefault(systemTz); + } + + @After + public void resetTimeZone() { + TimeZone.setDefault(testTz); + } + + private String functionCall; + private String name; + private Boolean expectedResult; + + public DateTimeComparisonIT(@Name("functionCall") String functionCall, + @Name("name") String name, + @Name("expectedResult") Boolean expectedResult) { + this.functionCall = functionCall; + this.name = name; + this.expectedResult = expectedResult; + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareTwoDates() { + return Arrays.asList($$( + $("DATE('2020-09-16') = DATE('2020-09-16')", "eq1", true), + $("DATE('2020-09-16') = DATE('1961-04-12')", "eq2", false), + $("DATE('2020-09-16') != DATE('1984-12-15')", "neq1", true), + $("DATE('1961-04-12') != DATE('1984-12-15')", "neq2", true), + $("DATE('1961-04-12') != DATE('1961-04-12')", "neq3", false), + $("DATE('1984-12-15') > DATE('1961-04-12')", "gt1", true), + $("DATE('1984-12-15') > DATE('2020-09-16')", "gt2", false), + $("DATE('1961-04-12') < DATE('1984-12-15')", "lt1", true), + $("DATE('1984-12-15') < DATE('1961-04-12')", "lt2", false), + $("DATE('1984-12-15') >= DATE('1961-04-12')", "gte1", true), + $("DATE('1984-12-15') >= DATE('1984-12-15')", "gte2", true), + $("DATE('1984-12-15') >= DATE('2020-09-16')", "gte3", false), + $("DATE('1961-04-12') <= DATE('1984-12-15')", "lte1", true), + $("DATE('1961-04-12') <= DATE('1961-04-12')", "lte2", true), + $("DATE('2020-09-16') <= DATE('1961-04-12')", "lte3", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareTwoTimes() { + return Arrays.asList($$( + $("TIME('09:16:37') = TIME('09:16:37')", "eq1", true), + $("TIME('09:16:37') = TIME('04:12:42')", "eq2", false), + $("TIME('09:16:37') != TIME('12:15:22')", "neq1", true), + $("TIME('04:12:42') != TIME('12:15:22')", "neq2", true), + $("TIME('04:12:42') != TIME('04:12:42')", "neq3", false), + $("TIME('12:15:22') > TIME('04:12:42')", "gt1", true), + $("TIME('12:15:22') > TIME('19:16:03')", "gt2", false), + $("TIME('04:12:42') < TIME('12:15:22')", "lt1", true), + $("TIME('14:12:38') < TIME('12:15:22')", "lt2", false), + $("TIME('12:15:22') >= TIME('04:12:42')", "gte1", true), + $("TIME('12:15:22') >= TIME('12:15:22')", "gte2", true), + $("TIME('12:15:22') >= TIME('19:16:03')", "gte3", false), + $("TIME('04:12:42') <= TIME('12:15:22')", "lte1", true), + $("TIME('04:12:42') <= TIME('04:12:42')", "lte2", true), + $("TIME('19:16:03') <= TIME('04:12:42')", "lte3", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareTwoDateTimes() { + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') = DATETIME('2020-09-16 10:20:30')", "eq1", true), + $("DATETIME('2020-09-16 10:20:30') = DATETIME('1961-04-12 09:07:00')", "eq2", false), + $("DATETIME('2020-09-16 10:20:30') != DATETIME('1984-12-15 22:15:07')", "neq1", true), + $("DATETIME('1984-12-15 22:15:08') != DATETIME('1984-12-15 22:15:07')", "neq2", true), + $("DATETIME('1961-04-12 09:07:00') != DATETIME('1961-04-12 09:07:00')", "neq3", false), + $("DATETIME('1984-12-15 22:15:07') > DATETIME('1961-04-12 22:15:07')", "gt1", true), + $("DATETIME('1984-12-15 22:15:07') > DATETIME('1984-12-15 22:15:06')", "gt2", true), + $("DATETIME('1984-12-15 22:15:07') > DATETIME('2020-09-16 10:20:30')", "gt3", false), + $("DATETIME('1961-04-12 09:07:00') < DATETIME('1984-12-15 09:07:00')", "lt1", true), + $("DATETIME('1984-12-15 22:15:07') < DATETIME('1984-12-15 22:15:08')", "lt2", true), + $("DATETIME('1984-12-15 22:15:07') < DATETIME('1961-04-12 09:07:00')", "lt3", false), + $("DATETIME('1984-12-15 22:15:07') >= DATETIME('1961-04-12 09:07:00')", "gte1", true), + $("DATETIME('1984-12-15 22:15:07') >= DATETIME('1984-12-15 22:15:07')", "gte2", true), + $("DATETIME('1984-12-15 22:15:07') >= DATETIME('2020-09-16 10:20:30')", "gte3", false), + $("DATETIME('1961-04-12 09:07:00') <= DATETIME('1984-12-15 22:15:07')", "lte1", true), + $("DATETIME('1961-04-12 09:07:00') <= DATETIME('1961-04-12 09:07:00')", "lte2", true), + $("DATETIME('2020-09-16 10:20:30') <= DATETIME('1961-04-12 09:07:00')", "lte3", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareTwoTimestamps() { + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') = TIMESTAMP('2020-09-16 10:20:30')", "eq1", true), + $("TIMESTAMP('2020-09-16 10:20:30') = TIMESTAMP('1961-04-12 09:07:00')", "eq2", false), + $("TIMESTAMP('2020-09-16 10:20:30') != TIMESTAMP('1984-12-15 22:15:07')", "neq1", true), + $("TIMESTAMP('1984-12-15 22:15:08') != TIMESTAMP('1984-12-15 22:15:07')", "neq2", true), + $("TIMESTAMP('1961-04-12 09:07:00') != TIMESTAMP('1961-04-12 09:07:00')", "neq3", false), + $("TIMESTAMP('1984-12-15 22:15:07') > TIMESTAMP('1961-04-12 22:15:07')", "gt1", true), + $("TIMESTAMP('1984-12-15 22:15:07') > TIMESTAMP('1984-12-15 22:15:06')", "gt2", true), + $("TIMESTAMP('1984-12-15 22:15:07') > TIMESTAMP('2020-09-16 10:20:30')", "gt3", false), + $("TIMESTAMP('1961-04-12 09:07:00') < TIMESTAMP('1984-12-15 09:07:00')", "lt1", true), + $("TIMESTAMP('1984-12-15 22:15:07') < TIMESTAMP('1984-12-15 22:15:08')", "lt2", true), + $("TIMESTAMP('1984-12-15 22:15:07') < TIMESTAMP('1961-04-12 09:07:00')", "lt3", false), + $("TIMESTAMP('1984-12-15 22:15:07') >= TIMESTAMP('1961-04-12 09:07:00')", "gte1", true), + $("TIMESTAMP('1984-12-15 22:15:07') >= TIMESTAMP('1984-12-15 22:15:07')", "gte2", true), + $("TIMESTAMP('1984-12-15 22:15:07') >= TIMESTAMP('2020-09-16 10:20:30')", "gte3", false), + $("TIMESTAMP('1961-04-12 09:07:00') <= TIMESTAMP('1984-12-15 22:15:07')", "lte1", true), + $("TIMESTAMP('1961-04-12 09:07:00') <= TIMESTAMP('1961-04-12 09:07:00')", "lte2", true), + $("TIMESTAMP('2020-09-16 10:20:30') <= TIMESTAMP('1961-04-12 09:07:00')", "lte3", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareEqTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') = DATETIME('2020-09-16 10:20:30')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') = TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') = DATETIME('1961-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('1961-04-12 09:07:00') = TIMESTAMP('1984-12-15 22:15:07')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 00:00:00') = DATE('2020-09-16')", "ts_d_t", true), + $("DATE('2020-09-16') = TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') = DATE('1961-04-12')", "ts_d_f", false), + $("DATE('1961-04-12') = TIMESTAMP('1984-12-15 22:15:07')", "d_ts_f", false), + $("TIMESTAMP('" + today + " 10:20:30') = TIME('10:20:30')", "ts_t_t", true), + $("TIME('10:20:30') = TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') = TIME('09:07:00')", "ts_t_f", false), + $("TIME('09:07:00') = TIMESTAMP('1984-12-15 22:15:07')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareEqDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') = TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') = DATETIME('2020-09-16 10:20:30')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') = TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('1961-04-12 09:07:00') = DATETIME('1984-12-15 22:15:07')", "ts_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') = DATE('2020-09-16')", "dt_d_t", true), + $("DATE('2020-09-16') = DATETIME('2020-09-16 00:00:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') = DATE('1961-04-12')", "dt_d_f", false), + $("DATE('1961-04-12') = DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('" + today + " 10:20:30') = TIME('10:20:30')", "dt_t_t", true), + $("TIME('10:20:30') = DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') = TIME('09:07:00')", "dt_t_f", false), + $("TIME('09:07:00') = DATETIME('1984-12-15 22:15:07')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareEqDateWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATE('2020-09-16') = TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 00:00:00') = DATE('2020-09-16')", "ts_d_t", true), + $("DATE('2020-09-16') = TIMESTAMP('1961-04-12 09:07:00')", "d_ts_f", false), + $("TIMESTAMP('1984-12-15 09:07:00') = DATE('1984-12-15')", "ts_d_f", false), + $("DATE('2020-09-16') = DATETIME('2020-09-16 00:00:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') = DATE('2020-09-16')", "dt_d_t", true), + $("DATE('1961-04-12') = DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('1961-04-12 10:20:30') = DATE('1961-04-12')", "dt_d_f", false), + $("DATE('" + today + "') = TIME('00:00:00')", "d_t_t", true), + $("TIME('00:00:00') = DATE('" + today + "')", "t_d_t", true), + $("DATE('2020-09-16') = TIME('09:07:00')", "d_t_f", false), + $("TIME('09:07:00') = DATE('" + today + "')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareEqTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('10:20:30') = DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('" + today + " 10:20:30') = TIME('10:20:30')", "dt_t_t", true), + $("TIME('09:07:00') = DATETIME('1961-04-12 09:07:00')", "t_dt_f", false), + $("DATETIME('" + today + " 09:07:00') = TIME('10:20:30')", "dt_t_f", false), + $("TIME('10:20:30') = TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 10:20:30') = TIME('10:20:30')", "ts_t_t", true), + $("TIME('22:15:07') = TIMESTAMP('1984-12-15 22:15:07')", "t_ts_f", false), + $("TIMESTAMP('1984-12-15 10:20:30') = TIME('10:20:30')", "ts_t_f", false), + $("TIME('00:00:00') = DATE('" + today + "')", "t_d_t", true), + $("DATE('" + today + "') = TIME('00:00:00')", "d_t_t", true), + $("TIME('09:07:00') = DATE('" + today + "')", "t_d_f", false), + $("DATE('2020-09-16') = TIME('09:07:00')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareNeqTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') != DATETIME('1961-04-12 09:07:00')", "ts_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') != TIMESTAMP('1984-12-15 22:15:07')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') != DATETIME('2020-09-16 10:20:30')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') != TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') != DATE('1961-04-12')", "ts_d_t", true), + $("DATE('1961-04-12') != TIMESTAMP('1984-12-15 22:15:07')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 00:00:00') != DATE('2020-09-16')", "ts_d_f", false), + $("DATE('2020-09-16') != TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') != TIME('09:07:00')", "ts_t_t", true), + $("TIME('09:07:00') != TIMESTAMP('1984-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 10:20:30') != TIME('10:20:30')", "ts_t_f", false), + $("TIME('10:20:30') != TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareNeqDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') != TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') != DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') != TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') != DATETIME('2020-09-16 10:20:30')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') != DATE('1961-04-12')", "dt_d_t", true), + $("DATE('1961-04-12') != DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') != DATE('2020-09-16')", "dt_d_f", false), + $("DATE('2020-09-16') != DATETIME('2020-09-16 00:00:00')", "d_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') != TIME('09:07:00')", "dt_t_t", true), + $("TIME('09:07:00') != DATETIME('1984-12-15 22:15:07')", "t_dt_t", true), + $("DATETIME('" + today + " 10:20:30') != TIME('10:20:30')", "dt_t_f", false), + $("TIME('10:20:30') != DATETIME('" + today + " 10:20:30')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareNeqDateWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATE('2020-09-16') != TIMESTAMP('1961-04-12 09:07:00')", "d_ts_t", true), + $("TIMESTAMP('1984-12-15 09:07:00') != DATE('1984-12-15')", "ts_d_t", true), + $("DATE('2020-09-16') != TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('2020-09-16 00:00:00') != DATE('2020-09-16')", "ts_d_f", false), + $("DATE('1961-04-12') != DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('1961-04-12 10:20:30') != DATE('1961-04-12')", "dt_d_t", true), + $("DATE('2020-09-16') != DATETIME('2020-09-16 00:00:00')", "d_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') != DATE('2020-09-16')", "dt_d_f", false), + $("DATE('2020-09-16') != TIME('09:07:00')", "d_t_t", true), + $("TIME('09:07:00') != DATE('" + today + "')", "t_d_t", true), + $("DATE('" + today + "') != TIME('00:00:00')", "d_t_f", false), + $("TIME('00:00:00') != DATE('" + today + "')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareNeqTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('09:07:00') != DATETIME('1961-04-12 09:07:00')", "t_dt_t", true), + $("DATETIME('" + today + " 09:07:00') != TIME('10:20:30')", "dt_t_t", true), + $("TIME('10:20:30') != DATETIME('" + today + " 10:20:30')", "t_dt_f", false), + $("DATETIME('" + today + " 10:20:30') != TIME('10:20:30')", "dt_t_f", false), + $("TIME('22:15:07') != TIMESTAMP('1984-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('1984-12-15 10:20:30') != TIME('10:20:30')", "ts_t_t", true), + $("TIME('10:20:30') != TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false), + $("TIMESTAMP('" + today + " 10:20:30') != TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') != DATE('" + today + "')", "t_d_t", true), + $("DATE('2020-09-16') != TIME('09:07:00')", "d_t_t", true), + $("TIME('00:00:00') != DATE('" + today + "')", "t_d_f", false), + $("DATE('" + today + "') != TIME('00:00:00')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLtTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') < DATETIME('2061-04-12 09:07:00')", "ts_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') < TIMESTAMP('1984-12-15 22:15:07')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') < DATETIME('2020-09-16 10:20:30')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') < TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') < DATE('2077-04-12')", "ts_d_t", true), + $("DATE('1961-04-12') < TIMESTAMP('1984-12-15 22:15:07')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') < DATE('1961-04-12')", "ts_d_f", false), + $("DATE('2020-09-16') < TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') < TIME('09:07:00')", "ts_t_t", true), + $("TIME('09:07:00') < TIMESTAMP('3077-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 10:20:30') < TIME('10:20:30')", "ts_t_f", false), + $("TIME('20:50:40') < TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLtDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') < TIMESTAMP('2077-04-12 09:07:00')", "dt_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') < DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') < TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') < DATETIME('1984-12-15 22:15:07')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') < DATE('3077-04-12')", "dt_d_t", true), + $("DATE('1961-04-12') < DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') < DATE('2020-09-16')", "dt_d_f", false), + $("DATE('2020-09-16') < DATETIME('1961-04-12 09:07:00')", "d_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') < TIME('09:07:00')", "dt_t_t", true), + $("TIME('09:07:00') < DATETIME('3077-12-15 22:15:07')", "t_dt_t", true), + $("DATETIME('" + today + " 10:20:30') < TIME('10:20:30')", "dt_t_f", false), + $("TIME('20:40:50') < DATETIME('" + today + " 10:20:30')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLtDateWithOtherTypes() { + return Arrays.asList($$( + $("DATE('2020-09-16') < TIMESTAMP('3077-04-12 09:07:00')", "d_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') < DATE('1984-12-15')", "ts_d_t", true), + $("DATE('2020-09-16') < TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('2077-04-12 09:07:00') < DATE('2020-09-16')", "ts_d_f", false), + $("DATE('1961-04-12') < DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('1961-04-12 10:20:30') < DATE('1984-11-15')", "dt_d_t", true), + $("DATE('2020-09-16') < DATETIME('2020-09-16 00:00:00')", "d_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') < DATE('1984-03-22')", "dt_d_f", false), + $("DATE('2020-09-16') < TIME('09:07:00')", "d_t_t", true), + $("TIME('09:07:00') < DATE('3077-04-12')", "t_d_t", true), + $("DATE('3077-04-12') < TIME('00:00:00')", "d_t_f", false), + $("TIME('00:00:00') < DATE('2020-09-16')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLtTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('09:07:00') < DATETIME('3077-04-12 09:07:00')", "t_dt_t", true), + $("DATETIME('" + today + " 09:07:00') < TIME('10:20:30')", "dt_t_t", true), + $("TIME('10:20:30') < DATETIME('" + today + " 10:20:30')", "t_dt_f", false), + $("DATETIME('" + today + " 20:40:50') < TIME('10:20:30')", "dt_t_f", false), + $("TIME('22:15:07') < TIMESTAMP('3077-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('1984-12-15 10:20:30') < TIME('10:20:30')", "ts_t_t", true), + $("TIME('10:20:30') < TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false), + $("TIMESTAMP('" + today + " 20:50:42') < TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') < DATE('3077-04-12')", "t_d_t", true), + $("DATE('2020-09-16') < TIME('09:07:00')", "d_t_t", true), + $("TIME('00:00:00') < DATE('1961-04-12')", "t_d_f", false), + $("DATE('3077-04-12') < TIME('10:20:30')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGtTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') > DATETIME('2020-09-16 10:20:25')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') > TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') > DATETIME('2061-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('1961-04-12 09:07:00') > TIMESTAMP('1984-12-15 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') > DATE('1961-04-12')", "ts_d_t", true), + $("DATE('2020-09-16') > TIMESTAMP('2020-09-15 22:15:07')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') > DATE('2077-04-12')", "ts_d_f", false), + $("DATE('1961-04-12') > TIMESTAMP('1961-04-12 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('3077-07-08 20:20:30') > TIME('10:20:30')", "ts_t_t", true), + $("TIME('20:50:40') > TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 10:20:30') > TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') > TIMESTAMP('3077-12-15 22:15:07')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGtDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:31') > TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') > DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') > TIMESTAMP('2077-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('1961-04-12 09:07:00') > DATETIME('1961-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('3077-04-12 10:20:30') > DATE('2020-09-16')", "dt_d_t", true), + $("DATE('2020-09-16') > DATETIME('1961-04-12 09:07:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') > DATE('2020-09-16')", "dt_d_f", false), + $("DATE('1961-04-12') > DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('3077-04-12 10:20:30') > TIME('09:07:00')", "dt_t_t", true), + $("TIME('20:40:50') > DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('" + today + " 10:20:30') > TIME('10:20:30')", "dt_t_f", false), + $("TIME('09:07:00') > DATETIME('3077-12-15 22:15:07')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGtDateWithOtherTypes() { + return Arrays.asList($$( + $("DATE('2020-09-16') > TIMESTAMP('1961-04-12 09:07:00')", "d_ts_t", true), + $("TIMESTAMP('2077-04-12 09:07:00') > DATE('2020-09-16')", "ts_d_t", true), + $("DATE('2020-09-16') > TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('1961-04-12 09:07:00') > DATE('1984-12-15')", "ts_d_f", false), + $("DATE('1984-12-15') > DATETIME('1961-04-12 09:07:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') > DATE('1984-03-22')", "dt_d_t", true), + $("DATE('2020-09-16') > DATETIME('2020-09-16 00:00:00')", "d_dt_f", false), + $("DATETIME('1961-04-12 10:20:30') > DATE('1984-11-15')", "dt_d_f", false), + $("DATE('3077-04-12') > TIME('00:00:00')", "d_t_t", true), + $("TIME('00:00:00') > DATE('2020-09-16')", "t_d_t", true), + $("DATE('2020-09-16') > TIME('09:07:00')", "d_t_f", false), + $("TIME('09:07:00') > DATE('3077-04-12')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGtTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('09:07:00') > DATETIME('1961-04-12 09:07:00')", "t_dt_t", true), + $("DATETIME('" + today + " 20:40:50') > TIME('10:20:30')", "dt_t_t", true), + $("TIME('10:20:30') > DATETIME('" + today + " 10:20:30')", "t_dt_f", false), + $("DATETIME('" + today + " 09:07:00') > TIME('10:20:30')", "dt_t_f", false), + $("TIME('22:15:07') > TIMESTAMP('1984-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 20:50:42') > TIME('10:20:30')", "ts_t_t", true), + $("TIME('10:20:30') > TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false), + $("TIMESTAMP('1984-12-15 10:20:30') > TIME('10:20:30')", "ts_t_f", false), + $("TIME('00:00:00') > DATE('1961-04-12')", "t_d_t", true), + $("DATE('3077-04-12') > TIME('10:20:30')", "d_t_t", true), + $("TIME('09:07:00') > DATE('3077-04-12')", "t_d_f", false), + $("DATE('2020-09-16') > TIME('09:07:00')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLteTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') <= DATETIME('2020-09-16 10:20:30')", "ts_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') <= TIMESTAMP('1984-12-15 22:15:07')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') <= DATETIME('1961-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') <= TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') <= DATE('2077-04-12')", "ts_d_t", true), + $("DATE('2020-09-16') <= TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') <= DATE('1961-04-12')", "ts_d_f", false), + $("DATE('2077-04-12') <= TIMESTAMP('1984-12-15 22:15:07')", "d_ts_f", false), + $("TIMESTAMP('" + today + " 10:20:30') <= TIME('10:20:30')", "ts_t_t", true), + $("TIME('09:07:00') <= TIMESTAMP('3077-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('3077-09-16 10:20:30') <= TIME('09:07:00')", "ts_t_f", false), + $("TIME('20:50:40') <= TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLteDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') <= TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') <= DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('3077-09-16 10:20:30') <= TIMESTAMP('2077-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') <= DATETIME('1984-12-15 22:15:07')", "ts_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') <= DATE('2020-09-16')", "dt_d_t", true), + $("DATE('1961-04-12') <= DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') <= DATE('1984-04-12')", "dt_d_f", false), + $("DATE('2020-09-16') <= DATETIME('1961-04-12 09:07:00')", "d_dt_f", false), + $("DATETIME('" + today + " 10:20:30') <= TIME('10:20:30')", "dt_t_t", true), + $("TIME('09:07:00') <= DATETIME('3077-12-15 22:15:07')", "t_dt_t", true), + $("DATETIME('3077-09-16 10:20:30') <= TIME('19:07:00')", "dt_t_f", false), + $("TIME('20:40:50') <= DATETIME('" + today + " 10:20:30')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLteDateWithOtherTypes() { + return Arrays.asList($$( + $("DATE('2020-09-16') <= TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') <= DATE('1984-12-15')", "ts_d_t", true), + $("DATE('2020-09-16') <= TIMESTAMP('1961-04-12 09:07:00')", "d_ts_f", false), + $("TIMESTAMP('2077-04-12 09:07:00') <= DATE('2020-09-16')", "ts_d_f", false), + $("DATE('2020-09-16') <= DATETIME('2020-09-16 00:00:00')", "d_dt_t", true), + $("DATETIME('1961-04-12 10:20:30') <= DATE('1984-11-15')", "dt_d_t", true), + $("DATE('2077-04-12') <= DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') <= DATE('1984-03-22')", "dt_d_f", false), + $("DATE('2020-09-16') <= TIME('09:07:00')", "d_t_t", true), + $("TIME('09:07:00') <= DATE('3077-04-12')", "t_d_t", true), + $("DATE('3077-04-12') <= TIME('00:00:00')", "d_t_f", false), + $("TIME('00:00:00') <= DATE('2020-09-16')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLteTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('10:20:30') <= DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('" + today + " 09:07:00') <= TIME('10:20:30')", "dt_t_t", true), + $("TIME('09:07:00') <= DATETIME('1961-04-12 09:07:00')", "t_dt_f", false), + $("DATETIME('" + today + " 20:40:50') <= TIME('10:20:30')", "dt_t_f", false), + $("TIME('10:20:30') <= TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('1984-12-15 10:20:30') <= TIME('10:20:30')", "ts_t_t", true), + $("TIME('22:15:07') <= TIMESTAMP('1984-12-15 22:15:07')", "t_ts_f", false), + $("TIMESTAMP('" + today + " 20:50:42') <= TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') <= DATE('3077-04-12')", "t_d_t", true), + $("DATE('2020-09-16') <= TIME('09:07:00')", "d_t_t", true), + $("TIME('00:00:00') <= DATE('1961-04-12')", "t_d_f", false), + $("DATE('3077-04-12') <= TIME('10:20:30')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGteTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') >= DATETIME('2020-09-16 10:20:30')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') >= TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') >= DATETIME('2061-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('1961-04-12 09:07:00') >= TIMESTAMP('1984-12-15 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') >= DATE('1961-04-12')", "ts_d_t", true), + $("DATE('2020-09-16') >= TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') >= DATE('2077-04-12')", "ts_d_f", false), + $("DATE('1961-04-11') >= TIMESTAMP('1961-04-12 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('" + today + " 10:20:30') >= TIME('10:20:30')", "ts_t_t", true), + $("TIME('20:50:40') >= TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('1977-07-08 10:20:30') >= TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') >= TIMESTAMP('3077-12-15 22:15:07')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGteDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') >= TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') >= DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') >= TIMESTAMP('2077-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('1961-04-12 00:00:00') >= DATETIME('1961-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') >= DATE('2020-09-16')", "dt_d_t", true), + $("DATE('2020-09-16') >= DATETIME('1961-04-12 09:07:00')", "d_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') >= DATE('2020-09-16')", "dt_d_f", false), + $("DATE('1961-04-12') >= DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('" + today + " 10:20:30') >= TIME('10:20:30')", "dt_t_t", true), + $("TIME('20:40:50') >= DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') >= TIME('09:07:00')", "dt_t_f", false), + $("TIME('09:07:00') >= DATETIME('3077-12-15 22:15:07')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGteDateWithOtherTypes() { + return Arrays.asList($$( + $("DATE('2020-09-16') >= TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2077-04-12 09:07:00') >= DATE('2020-09-16')", "ts_d_t", true), + $("DATE('1961-04-12') >= TIMESTAMP('1961-04-12 09:07:00')", "d_ts_f", false), + $("TIMESTAMP('1961-04-12 09:07:00') >= DATE('1984-12-15')", "ts_d_f", false), + $("DATE('2020-09-16') >= DATETIME('2020-09-16 00:00:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') >= DATE('1984-03-22')", "dt_d_t", true), + $("DATE('1960-12-15') >= DATETIME('1961-04-12 09:07:00')", "d_dt_f", false), + $("DATETIME('1961-04-12 10:20:30') >= DATE('1984-11-15')", "dt_d_f", false), + $("DATE('3077-04-12') >= TIME('00:00:00')", "d_t_t", true), + $("TIME('00:00:00') >= DATE('2020-09-16')", "t_d_t", true), + $("DATE('2020-09-16') >= TIME('09:07:00')", "d_t_f", false), + $("TIME('09:07:00') >= DATE('3077-04-12')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGteTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('10:20:30') >= DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('" + today + " 20:40:50') >= TIME('10:20:30')", "dt_t_t", true), + $("TIME('09:07:00') >= DATETIME('3077-04-12 09:07:00')", "t_dt_f", false), + $("DATETIME('" + today + " 09:07:00') >= TIME('10:20:30')", "dt_t_f", false), + $("TIME('10:20:30') >= TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 20:50:42') >= TIME('10:20:30')", "ts_t_t", true), + $("TIME('22:15:07') >= TIMESTAMP('3077-12-15 22:15:07')", "t_ts_f", false), + $("TIMESTAMP('1984-12-15 10:20:30') >= TIME('10:20:30')", "ts_t_f", false), + $("TIME('00:00:00') >= DATE('1961-04-12')", "t_d_t", true), + $("DATE('3077-04-12') >= TIME('10:20:30')", "d_t_t", true), + $("TIME('09:07:00') >= DATE('3077-04-12')", "t_d_f", false), + $("DATE('2020-09-16') >= TIME('09:07:00')", "d_t_f", false) + )); + } + + @Test + public void testCompare() throws IOException { + var result = executeQuery(String.format("source=%s | eval `%s` = %s | fields `%s`", + TEST_INDEX_DATATYPE_NONNUMERIC, name, functionCall, name)); + verifySchema(result, schema(name, null, "boolean")); + verifyDataRows(result, rows(expectedResult)); + } +} diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeComparisonIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeComparisonIT.java new file mode 100644 index 0000000000..108687da27 --- /dev/null +++ b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeComparisonIT.java @@ -0,0 +1,624 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.sql; + +import static com.carrotsearch.randomizedtesting.RandomizedTest.$; +import static com.carrotsearch.randomizedtesting.RandomizedTest.$$; +import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT; +import static org.opensearch.sql.util.MatcherUtils.rows; +import static org.opensearch.sql.util.MatcherUtils.schema; +import static org.opensearch.sql.util.MatcherUtils.verifyDataRows; +import static org.opensearch.sql.util.MatcherUtils.verifySchema; +import static org.opensearch.sql.util.TestUtils.getResponseBody; + +import java.io.IOException; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.Locale; +import java.util.TimeZone; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.jupiter.api.Test; +import org.opensearch.client.Request; +import org.opensearch.client.RequestOptions; +import org.opensearch.client.Response; +import org.opensearch.sql.legacy.SQLIntegTestCase; + +public class DateTimeComparisonIT extends SQLIntegTestCase { + + @Override + public void init() throws Exception { + super.init(); + } + + private final TimeZone testTz = TimeZone.getDefault(); + private final TimeZone systemTz = TimeZone.getTimeZone(System.getProperty("user.timezone")); + + @Before + public void setTimeZone() { + TimeZone.setDefault(systemTz); + } + + @After + public void resetTimeZone() { + TimeZone.setDefault(testTz); + } + + private String functionCall; + private String name; + private Boolean expectedResult; + + public DateTimeComparisonIT(@Name("functionCall") String functionCall, + @Name("name") String name, + @Name("expectedResult") Boolean expectedResult) { + this.functionCall = functionCall; + this.name = name; + this.expectedResult = expectedResult; + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareTwoDates() { + return Arrays.asList($$( + $("DATE('2020-09-16') = DATE('2020-09-16')", "eq1", true), + $("DATE('2020-09-16') = DATE('1961-04-12')", "eq2", false), + $("DATE('2020-09-16') != DATE('1984-12-15')", "neq1", true), + $("DATE('1961-04-12') != DATE('1984-12-15')", "neq2", true), + $("DATE('1961-04-12') != DATE('1961-04-12')", "neq3", false), + $("DATE('1984-12-15') > DATE('1961-04-12')", "gt1", true), + $("DATE('1984-12-15') > DATE('2020-09-16')", "gt2", false), + $("DATE('1961-04-12') < DATE('1984-12-15')", "lt1", true), + $("DATE('1984-12-15') < DATE('1961-04-12')", "lt2", false), + $("DATE('1984-12-15') >= DATE('1961-04-12')", "gte1", true), + $("DATE('1984-12-15') >= DATE('1984-12-15')", "gte2", true), + $("DATE('1984-12-15') >= DATE('2020-09-16')", "gte3", false), + $("DATE('1961-04-12') <= DATE('1984-12-15')", "lte1", true), + $("DATE('1961-04-12') <= DATE('1961-04-12')", "lte2", true), + $("DATE('2020-09-16') <= DATE('1961-04-12')", "lte3", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareTwoTimes() { + return Arrays.asList($$( + $("TIME('09:16:37') = TIME('09:16:37')", "eq1", true), + $("TIME('09:16:37') = TIME('04:12:42')", "eq2", false), + $("TIME('09:16:37') != TIME('12:15:22')", "neq1", true), + $("TIME('04:12:42') != TIME('12:15:22')", "neq2", true), + $("TIME('04:12:42') != TIME('04:12:42')", "neq3", false), + $("TIME('12:15:22') > TIME('04:12:42')", "gt1", true), + $("TIME('12:15:22') > TIME('19:16:03')", "gt2", false), + $("TIME('04:12:42') < TIME('12:15:22')", "lt1", true), + $("TIME('14:12:38') < TIME('12:15:22')", "lt2", false), + $("TIME('12:15:22') >= TIME('04:12:42')", "gte1", true), + $("TIME('12:15:22') >= TIME('12:15:22')", "gte2", true), + $("TIME('12:15:22') >= TIME('19:16:03')", "gte3", false), + $("TIME('04:12:42') <= TIME('12:15:22')", "lte1", true), + $("TIME('04:12:42') <= TIME('04:12:42')", "lte2", true), + $("TIME('19:16:03') <= TIME('04:12:42')", "lte3", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareTwoDateTimes() { + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') = DATETIME('2020-09-16 10:20:30')", "eq1", true), + $("DATETIME('2020-09-16 10:20:30') = DATETIME('1961-04-12 09:07:00')", "eq2", false), + $("DATETIME('2020-09-16 10:20:30') != DATETIME('1984-12-15 22:15:07')", "neq1", true), + $("DATETIME('1984-12-15 22:15:08') != DATETIME('1984-12-15 22:15:07')", "neq2", true), + $("DATETIME('1961-04-12 09:07:00') != DATETIME('1961-04-12 09:07:00')", "neq3", false), + $("DATETIME('1984-12-15 22:15:07') > DATETIME('1961-04-12 22:15:07')", "gt1", true), + $("DATETIME('1984-12-15 22:15:07') > DATETIME('1984-12-15 22:15:06')", "gt2", true), + $("DATETIME('1984-12-15 22:15:07') > DATETIME('2020-09-16 10:20:30')", "gt3", false), + $("DATETIME('1961-04-12 09:07:00') < DATETIME('1984-12-15 09:07:00')", "lt1", true), + $("DATETIME('1984-12-15 22:15:07') < DATETIME('1984-12-15 22:15:08')", "lt2", true), + $("DATETIME('1984-12-15 22:15:07') < DATETIME('1961-04-12 09:07:00')", "lt3", false), + $("DATETIME('1984-12-15 22:15:07') >= DATETIME('1961-04-12 09:07:00')", "gte1", true), + $("DATETIME('1984-12-15 22:15:07') >= DATETIME('1984-12-15 22:15:07')", "gte2", true), + $("DATETIME('1984-12-15 22:15:07') >= DATETIME('2020-09-16 10:20:30')", "gte3", false), + $("DATETIME('1961-04-12 09:07:00') <= DATETIME('1984-12-15 22:15:07')", "lte1", true), + $("DATETIME('1961-04-12 09:07:00') <= DATETIME('1961-04-12 09:07:00')", "lte2", true), + $("DATETIME('2020-09-16 10:20:30') <= DATETIME('1961-04-12 09:07:00')", "lte3", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareTwoTimestamps() { + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') = TIMESTAMP('2020-09-16 10:20:30')", "eq1", true), + $("TIMESTAMP('2020-09-16 10:20:30') = TIMESTAMP('1961-04-12 09:07:00')", "eq2", false), + $("TIMESTAMP('2020-09-16 10:20:30') != TIMESTAMP('1984-12-15 22:15:07')", "neq1", true), + $("TIMESTAMP('1984-12-15 22:15:08') != TIMESTAMP('1984-12-15 22:15:07')", "neq2", true), + $("TIMESTAMP('1961-04-12 09:07:00') != TIMESTAMP('1961-04-12 09:07:00')", "neq3", false), + $("TIMESTAMP('1984-12-15 22:15:07') > TIMESTAMP('1961-04-12 22:15:07')", "gt1", true), + $("TIMESTAMP('1984-12-15 22:15:07') > TIMESTAMP('1984-12-15 22:15:06')", "gt2", true), + $("TIMESTAMP('1984-12-15 22:15:07') > TIMESTAMP('2020-09-16 10:20:30')", "gt3", false), + $("TIMESTAMP('1961-04-12 09:07:00') < TIMESTAMP('1984-12-15 09:07:00')", "lt1", true), + $("TIMESTAMP('1984-12-15 22:15:07') < TIMESTAMP('1984-12-15 22:15:08')", "lt2", true), + $("TIMESTAMP('1984-12-15 22:15:07') < TIMESTAMP('1961-04-12 09:07:00')", "lt3", false), + $("TIMESTAMP('1984-12-15 22:15:07') >= TIMESTAMP('1961-04-12 09:07:00')", "gte1", true), + $("TIMESTAMP('1984-12-15 22:15:07') >= TIMESTAMP('1984-12-15 22:15:07')", "gte2", true), + $("TIMESTAMP('1984-12-15 22:15:07') >= TIMESTAMP('2020-09-16 10:20:30')", "gte3", false), + $("TIMESTAMP('1961-04-12 09:07:00') <= TIMESTAMP('1984-12-15 22:15:07')", "lte1", true), + $("TIMESTAMP('1961-04-12 09:07:00') <= TIMESTAMP('1961-04-12 09:07:00')", "lte2", true), + $("TIMESTAMP('2020-09-16 10:20:30') <= TIMESTAMP('1961-04-12 09:07:00')", "lte3", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareEqTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') = DATETIME('2020-09-16 10:20:30')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') = TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') = DATETIME('1961-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('1961-04-12 09:07:00') = TIMESTAMP('1984-12-15 22:15:07')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 00:00:00') = DATE('2020-09-16')", "ts_d_t", true), + $("DATE('2020-09-16') = TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') = DATE('1961-04-12')", "ts_d_f", false), + $("DATE('1961-04-12') = TIMESTAMP('1984-12-15 22:15:07')", "d_ts_f", false), + $("TIMESTAMP('" + today + " 10:20:30') = TIME('10:20:30')", "ts_t_t", true), + $("TIME('10:20:30') = TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') = TIME('09:07:00')", "ts_t_f", false), + $("TIME('09:07:00') = TIMESTAMP('1984-12-15 22:15:07')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareEqDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') = TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') = DATETIME('2020-09-16 10:20:30')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') = TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('1961-04-12 09:07:00') = DATETIME('1984-12-15 22:15:07')", "ts_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') = DATE('2020-09-16')", "dt_d_t", true), + $("DATE('2020-09-16') = DATETIME('2020-09-16 00:00:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') = DATE('1961-04-12')", "dt_d_f", false), + $("DATE('1961-04-12') = DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('" + today + " 10:20:30') = TIME('10:20:30')", "dt_t_t", true), + $("TIME('10:20:30') = DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') = TIME('09:07:00')", "dt_t_f", false), + $("TIME('09:07:00') = DATETIME('1984-12-15 22:15:07')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareEqDateWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATE('2020-09-16') = TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 00:00:00') = DATE('2020-09-16')", "ts_d_t", true), + $("DATE('2020-09-16') = TIMESTAMP('1961-04-12 09:07:00')", "d_ts_f", false), + $("TIMESTAMP('1984-12-15 09:07:00') = DATE('1984-12-15')", "ts_d_f", false), + $("DATE('2020-09-16') = DATETIME('2020-09-16 00:00:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') = DATE('2020-09-16')", "dt_d_t", true), + $("DATE('1961-04-12') = DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('1961-04-12 10:20:30') = DATE('1961-04-12')", "dt_d_f", false), + $("DATE('" + today + "') = TIME('00:00:00')", "d_t_t", true), + $("TIME('00:00:00') = DATE('" + today + "')", "t_d_t", true), + $("DATE('2020-09-16') = TIME('09:07:00')", "d_t_f", false), + $("TIME('09:07:00') = DATE('" + today + "')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareEqTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('10:20:30') = DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('" + today + " 10:20:30') = TIME('10:20:30')", "dt_t_t", true), + $("TIME('09:07:00') = DATETIME('1961-04-12 09:07:00')", "t_dt_f", false), + $("DATETIME('" + today + " 09:07:00') = TIME('10:20:30')", "dt_t_f", false), + $("TIME('10:20:30') = TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 10:20:30') = TIME('10:20:30')", "ts_t_t", true), + $("TIME('22:15:07') = TIMESTAMP('1984-12-15 22:15:07')", "t_ts_f", false), + $("TIMESTAMP('1984-12-15 10:20:30') = TIME('10:20:30')", "ts_t_f", false), + $("TIME('00:00:00') = DATE('" + today + "')", "t_d_t", true), + $("DATE('" + today + "') = TIME('00:00:00')", "d_t_t", true), + $("TIME('09:07:00') = DATE('" + today + "')", "t_d_f", false), + $("DATE('2020-09-16') = TIME('09:07:00')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareNeqTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') != DATETIME('1961-04-12 09:07:00')", "ts_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') != TIMESTAMP('1984-12-15 22:15:07')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') != DATETIME('2020-09-16 10:20:30')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') != TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') != DATE('1961-04-12')", "ts_d_t", true), + $("DATE('1961-04-12') != TIMESTAMP('1984-12-15 22:15:07')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 00:00:00') != DATE('2020-09-16')", "ts_d_f", false), + $("DATE('2020-09-16') != TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') != TIME('09:07:00')", "ts_t_t", true), + $("TIME('09:07:00') != TIMESTAMP('1984-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 10:20:30') != TIME('10:20:30')", "ts_t_f", false), + $("TIME('10:20:30') != TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareNeqDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') != TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') != DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') != TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') != DATETIME('2020-09-16 10:20:30')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') != DATE('1961-04-12')", "dt_d_t", true), + $("DATE('1961-04-12') != DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') != DATE('2020-09-16')", "dt_d_f", false), + $("DATE('2020-09-16') != DATETIME('2020-09-16 00:00:00')", "d_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') != TIME('09:07:00')", "dt_t_t", true), + $("TIME('09:07:00') != DATETIME('1984-12-15 22:15:07')", "t_dt_t", true), + $("DATETIME('" + today + " 10:20:30') != TIME('10:20:30')", "dt_t_f", false), + $("TIME('10:20:30') != DATETIME('" + today + " 10:20:30')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareNeqDateWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATE('2020-09-16') != TIMESTAMP('1961-04-12 09:07:00')", "d_ts_t", true), + $("TIMESTAMP('1984-12-15 09:07:00') != DATE('1984-12-15')", "ts_d_t", true), + $("DATE('2020-09-16') != TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('2020-09-16 00:00:00') != DATE('2020-09-16')", "ts_d_f", false), + $("DATE('1961-04-12') != DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('1961-04-12 10:20:30') != DATE('1961-04-12')", "dt_d_t", true), + $("DATE('2020-09-16') != DATETIME('2020-09-16 00:00:00')", "d_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') != DATE('2020-09-16')", "dt_d_f", false), + $("DATE('2020-09-16') != TIME('09:07:00')", "d_t_t", true), + $("TIME('09:07:00') != DATE('" + today + "')", "t_d_t", true), + $("DATE('" + today + "') != TIME('00:00:00')", "d_t_f", false), + $("TIME('00:00:00') != DATE('" + today + "')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareNeqTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('09:07:00') != DATETIME('1961-04-12 09:07:00')", "t_dt_t", true), + $("DATETIME('" + today + " 09:07:00') != TIME('10:20:30')", "dt_t_t", true), + $("TIME('10:20:30') != DATETIME('" + today + " 10:20:30')", "t_dt_f", false), + $("DATETIME('" + today + " 10:20:30') != TIME('10:20:30')", "dt_t_f", false), + $("TIME('22:15:07') != TIMESTAMP('1984-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('1984-12-15 10:20:30') != TIME('10:20:30')", "ts_t_t", true), + $("TIME('10:20:30') != TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false), + $("TIMESTAMP('" + today + " 10:20:30') != TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') != DATE('" + today + "')", "t_d_t", true), + $("DATE('2020-09-16') != TIME('09:07:00')", "d_t_t", true), + $("TIME('00:00:00') != DATE('" + today + "')", "t_d_f", false), + $("DATE('" + today + "') != TIME('00:00:00')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLtTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') < DATETIME('2061-04-12 09:07:00')", "ts_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') < TIMESTAMP('1984-12-15 22:15:07')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') < DATETIME('2020-09-16 10:20:30')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') < TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') < DATE('2077-04-12')", "ts_d_t", true), + $("DATE('1961-04-12') < TIMESTAMP('1984-12-15 22:15:07')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') < DATE('1961-04-12')", "ts_d_f", false), + $("DATE('2020-09-16') < TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') < TIME('09:07:00')", "ts_t_t", true), + $("TIME('09:07:00') < TIMESTAMP('3077-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 10:20:30') < TIME('10:20:30')", "ts_t_f", false), + $("TIME('20:50:40') < TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLtDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') < TIMESTAMP('2077-04-12 09:07:00')", "dt_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') < DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') < TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') < DATETIME('1984-12-15 22:15:07')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') < DATE('3077-04-12')", "dt_d_t", true), + $("DATE('1961-04-12') < DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') < DATE('2020-09-16')", "dt_d_f", false), + $("DATE('2020-09-16') < DATETIME('1961-04-12 09:07:00')", "d_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') < TIME('09:07:00')", "dt_t_t", true), + $("TIME('09:07:00') < DATETIME('3077-12-15 22:15:07')", "t_dt_t", true), + $("DATETIME('" + today + " 10:20:30') < TIME('10:20:30')", "dt_t_f", false), + $("TIME('20:40:50') < DATETIME('" + today + " 10:20:30')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLtDateWithOtherTypes() { + return Arrays.asList($$( + $("DATE('2020-09-16') < TIMESTAMP('3077-04-12 09:07:00')", "d_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') < DATE('1984-12-15')", "ts_d_t", true), + $("DATE('2020-09-16') < TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('2077-04-12 09:07:00') < DATE('2020-09-16')", "ts_d_f", false), + $("DATE('1961-04-12') < DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('1961-04-12 10:20:30') < DATE('1984-11-15')", "dt_d_t", true), + $("DATE('2020-09-16') < DATETIME('2020-09-16 00:00:00')", "d_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') < DATE('1984-03-22')", "dt_d_f", false), + $("DATE('2020-09-16') < TIME('09:07:00')", "d_t_t", true), + $("TIME('09:07:00') < DATE('3077-04-12')", "t_d_t", true), + $("DATE('3077-04-12') < TIME('00:00:00')", "d_t_f", false), + $("TIME('00:00:00') < DATE('2020-09-16')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLtTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('09:07:00') < DATETIME('3077-04-12 09:07:00')", "t_dt_t", true), + $("DATETIME('" + today + " 09:07:00') < TIME('10:20:30')", "dt_t_t", true), + $("TIME('10:20:30') < DATETIME('" + today + " 10:20:30')", "t_dt_f", false), + $("DATETIME('" + today + " 20:40:50') < TIME('10:20:30')", "dt_t_f", false), + $("TIME('22:15:07') < TIMESTAMP('3077-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('1984-12-15 10:20:30') < TIME('10:20:30')", "ts_t_t", true), + $("TIME('10:20:30') < TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false), + $("TIMESTAMP('" + today + " 20:50:42') < TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') < DATE('3077-04-12')", "t_d_t", true), + $("DATE('2020-09-16') < TIME('09:07:00')", "d_t_t", true), + $("TIME('00:00:00') < DATE('1961-04-12')", "t_d_f", false), + $("DATE('3077-04-12') < TIME('10:20:30')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGtTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') > DATETIME('2020-09-16 10:20:25')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') > TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') > DATETIME('2061-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('1961-04-12 09:07:00') > TIMESTAMP('1984-12-15 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') > DATE('1961-04-12')", "ts_d_t", true), + $("DATE('2020-09-16') > TIMESTAMP('2020-09-15 22:15:07')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') > DATE('2077-04-12')", "ts_d_f", false), + $("DATE('1961-04-12') > TIMESTAMP('1961-04-12 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('3077-07-08 20:20:30') > TIME('10:20:30')", "ts_t_t", true), + $("TIME('20:50:40') > TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 10:20:30') > TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') > TIMESTAMP('3077-12-15 22:15:07')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGtDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:31') > TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') > DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') > TIMESTAMP('2077-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('1961-04-12 09:07:00') > DATETIME('1961-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('3077-04-12 10:20:30') > DATE('2020-09-16')", "dt_d_t", true), + $("DATE('2020-09-16') > DATETIME('1961-04-12 09:07:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') > DATE('2020-09-16')", "dt_d_f", false), + $("DATE('1961-04-12') > DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('3077-04-12 10:20:30') > TIME('09:07:00')", "dt_t_t", true), + $("TIME('20:40:50') > DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('" + today + " 10:20:30') > TIME('10:20:30')", "dt_t_f", false), + $("TIME('09:07:00') > DATETIME('3077-12-15 22:15:07')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGtDateWithOtherTypes() { + return Arrays.asList($$( + $("DATE('2020-09-16') > TIMESTAMP('1961-04-12 09:07:00')", "d_ts_t", true), + $("TIMESTAMP('2077-04-12 09:07:00') > DATE('2020-09-16')", "ts_d_t", true), + $("DATE('2020-09-16') > TIMESTAMP('2020-09-16 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('1961-04-12 09:07:00') > DATE('1984-12-15')", "ts_d_f", false), + $("DATE('1984-12-15') > DATETIME('1961-04-12 09:07:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') > DATE('1984-03-22')", "dt_d_t", true), + $("DATE('2020-09-16') > DATETIME('2020-09-16 00:00:00')", "d_dt_f", false), + $("DATETIME('1961-04-12 10:20:30') > DATE('1984-11-15')", "dt_d_f", false), + $("DATE('3077-04-12') > TIME('00:00:00')", "d_t_t", true), + $("TIME('00:00:00') > DATE('2020-09-16')", "t_d_t", true), + $("DATE('2020-09-16') > TIME('09:07:00')", "d_t_f", false), + $("TIME('09:07:00') > DATE('3077-04-12')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGtTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('09:07:00') > DATETIME('1961-04-12 09:07:00')", "t_dt_t", true), + $("DATETIME('" + today + " 20:40:50') > TIME('10:20:30')", "dt_t_t", true), + $("TIME('10:20:30') > DATETIME('" + today + " 10:20:30')", "t_dt_f", false), + $("DATETIME('" + today + " 09:07:00') > TIME('10:20:30')", "dt_t_f", false), + $("TIME('22:15:07') > TIMESTAMP('1984-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 20:50:42') > TIME('10:20:30')", "ts_t_t", true), + $("TIME('10:20:30') > TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false), + $("TIMESTAMP('1984-12-15 10:20:30') > TIME('10:20:30')", "ts_t_f", false), + $("TIME('00:00:00') > DATE('1961-04-12')", "t_d_t", true), + $("DATE('3077-04-12') > TIME('10:20:30')", "d_t_t", true), + $("TIME('09:07:00') > DATE('3077-04-12')", "t_d_f", false), + $("DATE('2020-09-16') > TIME('09:07:00')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLteTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') <= DATETIME('2020-09-16 10:20:30')", "ts_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') <= TIMESTAMP('1984-12-15 22:15:07')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') <= DATETIME('1961-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('2020-09-16 10:20:30') <= TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') <= DATE('2077-04-12')", "ts_d_t", true), + $("DATE('2020-09-16') <= TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') <= DATE('1961-04-12')", "ts_d_f", false), + $("DATE('2077-04-12') <= TIMESTAMP('1984-12-15 22:15:07')", "d_ts_f", false), + $("TIMESTAMP('" + today + " 10:20:30') <= TIME('10:20:30')", "ts_t_t", true), + $("TIME('09:07:00') <= TIMESTAMP('3077-12-15 22:15:07')", "t_ts_t", true), + $("TIMESTAMP('3077-09-16 10:20:30') <= TIME('09:07:00')", "ts_t_f", false), + $("TIME('20:50:40') <= TIMESTAMP('" + today + " 10:20:30')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLteDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') <= TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') <= DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('3077-09-16 10:20:30') <= TIMESTAMP('2077-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') <= DATETIME('1984-12-15 22:15:07')", "ts_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') <= DATE('2020-09-16')", "dt_d_t", true), + $("DATE('1961-04-12') <= DATETIME('1984-12-15 22:15:07')", "d_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') <= DATE('1984-04-12')", "dt_d_f", false), + $("DATE('2020-09-16') <= DATETIME('1961-04-12 09:07:00')", "d_dt_f", false), + $("DATETIME('" + today + " 10:20:30') <= TIME('10:20:30')", "dt_t_t", true), + $("TIME('09:07:00') <= DATETIME('3077-12-15 22:15:07')", "t_dt_t", true), + $("DATETIME('3077-09-16 10:20:30') <= TIME('19:07:00')", "dt_t_f", false), + $("TIME('20:40:50') <= DATETIME('" + today + " 10:20:30')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLteDateWithOtherTypes() { + return Arrays.asList($$( + $("DATE('2020-09-16') <= TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('1961-04-12 09:07:00') <= DATE('1984-12-15')", "ts_d_t", true), + $("DATE('2020-09-16') <= TIMESTAMP('1961-04-12 09:07:00')", "d_ts_f", false), + $("TIMESTAMP('2077-04-12 09:07:00') <= DATE('2020-09-16')", "ts_d_f", false), + $("DATE('2020-09-16') <= DATETIME('2020-09-16 00:00:00')", "d_dt_t", true), + $("DATETIME('1961-04-12 10:20:30') <= DATE('1984-11-15')", "dt_d_t", true), + $("DATE('2077-04-12') <= DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') <= DATE('1984-03-22')", "dt_d_f", false), + $("DATE('2020-09-16') <= TIME('09:07:00')", "d_t_t", true), + $("TIME('09:07:00') <= DATE('3077-04-12')", "t_d_t", true), + $("DATE('3077-04-12') <= TIME('00:00:00')", "d_t_f", false), + $("TIME('00:00:00') <= DATE('2020-09-16')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareLteTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('10:20:30') <= DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('" + today + " 09:07:00') <= TIME('10:20:30')", "dt_t_t", true), + $("TIME('09:07:00') <= DATETIME('1961-04-12 09:07:00')", "t_dt_f", false), + $("DATETIME('" + today + " 20:40:50') <= TIME('10:20:30')", "dt_t_f", false), + $("TIME('10:20:30') <= TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('1984-12-15 10:20:30') <= TIME('10:20:30')", "ts_t_t", true), + $("TIME('22:15:07') <= TIMESTAMP('1984-12-15 22:15:07')", "t_ts_f", false), + $("TIMESTAMP('" + today + " 20:50:42') <= TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') <= DATE('3077-04-12')", "t_d_t", true), + $("DATE('2020-09-16') <= TIME('09:07:00')", "d_t_t", true), + $("TIME('00:00:00') <= DATE('1961-04-12')", "t_d_f", false), + $("DATE('3077-04-12') <= TIME('10:20:30')", "d_t_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGteTimestampWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIMESTAMP('2020-09-16 10:20:30') >= DATETIME('2020-09-16 10:20:30')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') >= TIMESTAMP('1961-04-12 09:07:00')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') >= DATETIME('2061-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('1961-04-12 09:07:00') >= TIMESTAMP('1984-12-15 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('2020-09-16 10:20:30') >= DATE('1961-04-12')", "ts_d_t", true), + $("DATE('2020-09-16') >= TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') >= DATE('2077-04-12')", "ts_d_f", false), + $("DATE('1961-04-11') >= TIMESTAMP('1961-04-12 00:00:00')", "d_ts_f", false), + $("TIMESTAMP('" + today + " 10:20:30') >= TIME('10:20:30')", "ts_t_t", true), + $("TIME('20:50:40') >= TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('1977-07-08 10:20:30') >= TIME('10:20:30')", "ts_t_f", false), + $("TIME('09:07:00') >= TIMESTAMP('3077-12-15 22:15:07')", "t_ts_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGteDateTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("DATETIME('2020-09-16 10:20:30') >= TIMESTAMP('2020-09-16 10:20:30')", "dt_ts_t", true), + $("TIMESTAMP('2020-09-16 10:20:30') >= DATETIME('1984-12-15 22:15:07')", "ts_dt_t", true), + $("DATETIME('2020-09-16 10:20:30') >= TIMESTAMP('2077-04-12 09:07:00')", "dt_ts_f", false), + $("TIMESTAMP('1961-04-12 00:00:00') >= DATETIME('1961-04-12 09:07:00')", "ts_dt_f", false), + $("DATETIME('2020-09-16 00:00:00') >= DATE('2020-09-16')", "dt_d_t", true), + $("DATE('2020-09-16') >= DATETIME('1961-04-12 09:07:00')", "d_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') >= DATE('2020-09-16')", "dt_d_f", false), + $("DATE('1961-04-12') >= DATETIME('1984-12-15 22:15:07')", "d_dt_f", false), + $("DATETIME('" + today + " 10:20:30') >= TIME('10:20:30')", "dt_t_t", true), + $("TIME('20:40:50') >= DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('1961-04-12 09:07:00') >= TIME('09:07:00')", "dt_t_f", false), + $("TIME('09:07:00') >= DATETIME('3077-12-15 22:15:07')", "t_dt_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGteDateWithOtherTypes() { + return Arrays.asList($$( + $("DATE('2020-09-16') >= TIMESTAMP('2020-09-16 00:00:00')", "d_ts_t", true), + $("TIMESTAMP('2077-04-12 09:07:00') >= DATE('2020-09-16')", "ts_d_t", true), + $("DATE('1961-04-12') >= TIMESTAMP('1961-04-12 09:07:00')", "d_ts_f", false), + $("TIMESTAMP('1961-04-12 09:07:00') >= DATE('1984-12-15')", "ts_d_f", false), + $("DATE('2020-09-16') >= DATETIME('2020-09-16 00:00:00')", "d_dt_t", true), + $("DATETIME('2020-09-16 00:00:00') >= DATE('1984-03-22')", "dt_d_t", true), + $("DATE('1960-12-15') >= DATETIME('1961-04-12 09:07:00')", "d_dt_f", false), + $("DATETIME('1961-04-12 10:20:30') >= DATE('1984-11-15')", "dt_d_f", false), + $("DATE('3077-04-12') >= TIME('00:00:00')", "d_t_t", true), + $("TIME('00:00:00') >= DATE('2020-09-16')", "t_d_t", true), + $("DATE('2020-09-16') >= TIME('09:07:00')", "d_t_f", false), + $("TIME('09:07:00') >= DATE('3077-04-12')", "t_d_f", false) + )); + } + + @ParametersFactory(argumentFormatting = "%1$s => %3$s") + public static Iterable compareGteTimeWithOtherTypes() { + var today = LocalDate.now().toString(); + return Arrays.asList($$( + $("TIME('10:20:30') >= DATETIME('" + today + " 10:20:30')", "t_dt_t", true), + $("DATETIME('" + today + " 20:40:50') >= TIME('10:20:30')", "dt_t_t", true), + $("TIME('09:07:00') >= DATETIME('3077-04-12 09:07:00')", "t_dt_f", false), + $("DATETIME('" + today + " 09:07:00') >= TIME('10:20:30')", "dt_t_f", false), + $("TIME('10:20:30') >= TIMESTAMP('" + today + " 10:20:30')", "t_ts_t", true), + $("TIMESTAMP('" + today + " 20:50:42') >= TIME('10:20:30')", "ts_t_t", true), + $("TIME('22:15:07') >= TIMESTAMP('3077-12-15 22:15:07')", "t_ts_f", false), + $("TIMESTAMP('1984-12-15 10:20:30') >= TIME('10:20:30')", "ts_t_f", false), + $("TIME('00:00:00') >= DATE('1961-04-12')", "t_d_t", true), + $("DATE('3077-04-12') >= TIME('10:20:30')", "d_t_t", true), + $("TIME('09:07:00') >= DATE('3077-04-12')", "t_d_f", false), + $("DATE('2020-09-16') >= TIME('09:07:00')", "d_t_f", false) + )); + } + + @Test + public void testCompare() throws IOException { + var result = executeQuery(String.format("select %s AS `%s`", functionCall, name)); + verifySchema(result, schema(functionCall, name, "boolean")); + verifyDataRows(result, rows(expectedResult)); + } + + protected JSONObject executeQuery(String query) throws IOException { + Request request = new Request("POST", QUERY_API_ENDPOINT); + request.setJsonEntity(String.format(Locale.ROOT, "{\n" + " \"query\": \"%s\"\n" + "}", query)); + + RequestOptions.Builder restOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); + restOptionsBuilder.addHeader("Content-Type", "application/json"); + request.setOptions(restOptionsBuilder); + + Response response = client().performRequest(request); + return new JSONObject(getResponseBody(response)); + } +}