From 982d366d1d8f11a9053acb6e72abb14eb3050476 Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 09:30:52 -0800 Subject: [PATCH] Extend comparison methods to accept different datetime types. (#129) (#1196) (#1294) * Extend comparison methods to accept different datetime types. (#129) * Extend comparison methods to accept different datetime types. Signed-off-by: Yury-Fridlyand Signed-off-by: Yury-Fridlyand * Typo fix. Signed-off-by: Yury-Fridlyand * Rework fix according to @dai-chen's comment. https://github.com/opensearch-project/sql/pull/1196#pullrequestreview-1239305900 * Revert `BinaryPredicateOperator`. * Add automatic cast rules `DATE`/`TIME`/`DATETIME` -> `DATETIME`/TIMESTAMP`. * Update unit tests. Signed-off-by: Yury-Fridlyand * Add doctest sample. Signed-off-by: Yury-Fridlyand * Docs typo fix. Signed-off-by: Yury-Fridlyand * Minor comments update. Signed-off-by: Yury-Fridlyand * Doctest typo fix. Signed-off-by: Yury-Fridlyand * Doctest typo fix. Signed-off-by: Yury-Fridlyand * Doctest typo fix. Signed-off-by: Yury-Fridlyand * Modify `ExprCoreType` dependencies. Signed-off-by: Yury-Fridlyand Signed-off-by: Yury-Fridlyand Signed-off-by: Yury-Fridlyand (cherry picked from commit a4f80663ecdd8cc7403d42cd7fdce06b0ccbd1fd) Co-authored-by: Yury-Fridlyand --- .../sql/data/model/AbstractExprValue.java | 6 +- .../sql/data/model/ExprDateValue.java | 5 + .../sql/data/model/ExprDatetimeValue.java | 5 + .../sql/data/model/ExprTimeValue.java | 5 + .../sql/data/model/ExprTimestampValue.java | 5 + .../opensearch/sql/data/model/ExprValue.java | 9 + .../sql/data/type/ExprCoreType.java | 5 +- .../org/opensearch/sql/expression/DSL.java | 36 +- .../operator/convert/TypeCastOperator.java | 14 +- .../sql/data/model/ExprBooleanValueTest.java | 49 +- .../sql/data/model/ExprStringValueTest.java | 60 ++ .../sql/data/model/ExprValueCompareTest.java | 185 +++++- .../function/WideningTypeRuleTest.java | 5 + .../BinaryPredicateOperatorTest.java | 188 ++++-- .../opensearch/sql/utils/ComparisonUtil.java | 61 +- docs/user/dql/expressions.rst | 28 + docs/user/ppl/functions/expressions.rst | 3 + .../sql/ppl/DateTimeComparisonIT.java | 607 +++++++++++++++++ .../sql/sql/DateTimeComparisonIT.java | 624 ++++++++++++++++++ 19 files changed, 1796 insertions(+), 104 deletions(-) create mode 100644 core/src/test/java/org/opensearch/sql/data/model/ExprStringValueTest.java create mode 100644 integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeComparisonIT.java create mode 100644 integ-test/src/test/java/org/opensearch/sql/sql/DateTimeComparisonIT.java 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 f665627838..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 @@ -71,6 +71,11 @@ public Instant timestampValue() { return ZonedDateTime.of(date, timeValue(), ExprTimestampValue.ZONE).toInstant(); } + @Override + public boolean isDateTime() { + return true; + } + @Override public String toString() { return String.format("DATE '%s'", value()); 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 628106b048..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 @@ -73,6 +73,11 @@ public Instant timestampValue() { return ZonedDateTime.of(datetime, ExprTimestampValue.ZONE).toInstant(); } + @Override + public boolean isDateTime() { + return true; + } + @Override public int compare(ExprValue other) { return datetime.compareTo(other.datetimeValue()); 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 d77a2615d2..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 @@ -70,6 +70,11 @@ public Instant timestampValue(FunctionProperties functionProperties) { .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 a7ae605a7f..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 @@ -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..1ae03de37b 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 Datetime 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/type/ExprCoreType.java b/core/src/main/java/org/opensearch/sql/data/type/ExprCoreType.java index ad2e42596d..a9ceeac4dc 100644 --- a/core/src/main/java/org/opensearch/sql/data/type/ExprCoreType.java +++ b/core/src/main/java/org/opensearch/sql/data/type/ExprCoreType.java @@ -53,12 +53,11 @@ public enum ExprCoreType implements ExprType { /** * Date. - * Todo. compatible relationship. */ - TIMESTAMP(STRING), DATE(STRING), TIME(STRING), - DATETIME(STRING), + DATETIME(STRING, DATE, TIME), + TIMESTAMP(STRING, DATETIME), INTERVAL(UNDEFINED), /** 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 0450181c3c..57ba773d30 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -540,28 +540,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/operator/convert/TypeCastOperator.java b/core/src/main/java/org/opensearch/sql/expression/operator/convert/TypeCastOperator.java index 8f904bfbf7..d3295a53f0 100644 --- a/core/src/main/java/org/opensearch/sql/expression/operator/convert/TypeCastOperator.java +++ b/core/src/main/java/org/opensearch/sql/expression/operator/convert/TypeCastOperator.java @@ -19,7 +19,9 @@ 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 java.util.Arrays; import java.util.stream.Collectors; @@ -176,12 +178,18 @@ private static DefaultFunctionResolver castToTime() { ); } + // `DATE`/`TIME`/`DATETIME` -> `DATETIME`/TIMESTAMP` cast tested in BinaryPredicateOperatorTest private static DefaultFunctionResolver castToTimestamp() { return FunctionDSL.define(BuiltinFunctionName.CAST_TO_TIMESTAMP.getName(), impl(nullMissingHandling( (v) -> new ExprTimestampValue(v.stringValue())), TIMESTAMP, STRING), impl(nullMissingHandling( (v) -> new ExprTimestampValue(v.timestampValue())), TIMESTAMP, DATETIME), + impl(nullMissingHandling( + (v) -> new ExprTimestampValue(v.timestampValue())), TIMESTAMP, DATE), + implWithProperties(nullMissingHandlingWithProperties( + (fp, v) -> new ExprTimestampValue(((ExprTimeValue)v).timestampValue(fp))), + TIMESTAMP, TIME), impl(nullMissingHandling((v) -> v), TIMESTAMP, TIMESTAMP) ); } @@ -193,7 +201,11 @@ private static DefaultFunctionResolver castToDatetime() { impl(nullMissingHandling( (v) -> new ExprDatetimeValue(v.datetimeValue())), DATETIME, TIMESTAMP), impl(nullMissingHandling( - (v) -> new ExprDatetimeValue(v.datetimeValue())), DATETIME, DATE) + (v) -> new ExprDatetimeValue(v.datetimeValue())), DATETIME, DATE), + implWithProperties(nullMissingHandlingWithProperties( + (fp, v) -> new ExprDatetimeValue(((ExprTimeValue)v).datetimeValue(fp))), + DATETIME, TIME), + impl(nullMissingHandling((v) -> v), DATETIME, DATETIME) ); } } 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/WideningTypeRuleTest.java b/core/src/test/java/org/opensearch/sql/expression/function/WideningTypeRuleTest.java index 7e494fc8b2..27b36a0fec 100644 --- a/core/src/test/java/org/opensearch/sql/expression/function/WideningTypeRuleTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/function/WideningTypeRuleTest.java @@ -61,6 +61,11 @@ class WideningTypeRuleTest { .put(STRING, DATE, 1) .put(STRING, TIME, 1) .put(STRING, DATETIME, 1) + .put(DATE, DATETIME, 1) + .put(TIME, DATETIME, 1) + .put(DATE, TIMESTAMP, 2) + .put(TIME, TIMESTAMP, 2) + .put(DATETIME, TIMESTAMP, 1) .put(UNDEFINED, BYTE, 1) .put(UNDEFINED, SHORT, 2) .put(UNDEFINED, INTEGER, 3) 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..4dcfde994f 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,13 @@ 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.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.STRUCT; +import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP; import static org.opensearch.sql.utils.ComparisonUtil.compare; import static org.opensearch.sql.utils.OperatorUtils.matches; @@ -34,6 +38,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,18 +53,10 @@ 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.data.type.ExprType; import org.opensearch.sql.expression.DSL; import org.opensearch.sql.expression.Expression; import org.opensearch.sql.expression.ExpressionTestBase; @@ -87,54 +88,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,11 +412,35 @@ 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()))); - assertEquals(String.format("=(%s, %s)", v1.toString(), v2.toString()), equal.toString()); + 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()))); + } + assertStringRepr(v1, v2, "=", equal); + } + + private void assertStringRepr(ExprValue v1, ExprValue v2, String function, + FunctionExpression functionExpression) { + if (v1.type() == v2.type()) { + assertEquals(String.format("%s(%s, %s)", function, v1, v2), functionExpression.toString()); + } else { + var widerType = v1.type() == TIMESTAMP || v2.type() == TIMESTAMP ? TIMESTAMP : DATETIME; + assertEquals(String.format("%s(%s, %s)", function, getExpectedStringRepr(widerType, v1), + getExpectedStringRepr(widerType, v2)), functionExpression.toString()); + } + } + + private String getExpectedStringRepr(ExprType widerType, ExprValue value) { + if (widerType == value.type()) { + return value.toString(); + } + return String.format("cast_to_%s(%s)", widerType.toString().toLowerCase(), value); } @Test @@ -426,11 +485,18 @@ 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()))); - assertEquals(String.format("!=(%s, %s)", v1.toString(), v2.toString()), notequal.toString()); + 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()))); + } + assertStringRepr(v1, v2, "!=", notequal); } @Test @@ -479,11 +545,11 @@ 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()); + assertStringRepr(v1, v2, "<", less); } @Test @@ -536,11 +602,11 @@ 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()); + assertStringRepr(v1, v2, "<=", lte); } @Test @@ -593,11 +659,11 @@ 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()); + assertStringRepr(v1, v2, ">", greater); } @Test @@ -650,11 +716,11 @@ 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()); + assertStringRepr(v1, v2, ">=", gte); } @Test 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 09818c902d..8507c56c34 100644 --- a/docs/user/dql/expressions.rst +++ b/docs/user/dql/expressions.rst @@ -150,6 +150,34 @@ 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. + + os> SELECT current_time() > current_date() AS `now.time > today`, typeof(current_time()) AS `now.time.type`, typeof(current_date()) AS `now.date.type`; + fetched rows / total rows = 1/1 + +--------------------+-----------------+-----------------+ + | now.time > today | now.time.type | now.date.type | + |--------------------+-----------------+-----------------| + | True | TIME | DATE | + +--------------------+-----------------+-----------------+ + + os> SELECT current_time() = now() AS `now.time = now`, typeof(current_time()) AS `now.time.type`, typeof(now()) AS `now.type`; + fetched rows / total rows = 1/1 + +------------------+-----------------+------------+ + | now.time = now | now.time.type | now.type | + |------------------+-----------------+------------| + | True | TIME | DATETIME | + +------------------+-----------------+------------+ + + os> SELECT subtime(now(), current_time()) = current_date() AS `midnight = now.date`, typeof(subtime(now(), current_time())) AS `midnight.type`, typeof(current_date()) AS `now.date.type`; + fetched rows / total rows = 1/1 + +-----------------------+-----------------+-----------------+ + | midnight = now.date | midnight.type | now.date.type | + |-----------------------+-----------------+-----------------| + | True | DATETIME | DATE | + +-----------------------+-----------------+-----------------+ + + 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)); + } +}