From 8f3d5659bb51c5a8e461c3af91da77c9152dedb9 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Thu, 20 Apr 2023 00:03:53 -0700 Subject: [PATCH] Minor clean up of datetime and other classes (#198) (#1310) * Minor clean up of datetime and other classes (#198) --------- Signed-off-by: MitchellGale-BitQuill Signed-off-by: Yury-Fridlyand --- .../opensearch/sql/ast/statement/Explain.java | 2 + .../org/opensearch/sql/ast/tree/Limit.java | 2 +- .../sql/data/model/ExprDateValue.java | 3 +- .../sql/data/model/ExprDatetimeValue.java | 25 +- .../sql/data/model/ExprTimeValue.java | 3 +- .../sql/data/model/ExprTimestampValue.java | 22 +- .../org/opensearch/sql/expression/DSL.java | 1 - .../expression/datetime/DateTimeFunction.java | 19 +- .../arthmetic/ArithmeticFunction.java | 218 ++-- .../arthmetic/MathematicalFunction.java | 308 +++--- .../predicate/BinaryPredicateOperator.java | 123 +-- .../sql/expression/parse/ParseExpression.java | 2 +- .../planner/physical/collector/Rounding.java | 12 +- .../sql/utils/DateTimeFormatters.java | 18 +- .../opensearch/sql/utils/DateTimeUtils.java | 14 +- .../sql/data/model/DateTimeValueTest.java | 9 +- .../sql/data/model/ExprValueUtilsTest.java | 4 +- .../expression/datetime/ConvertTZTest.java | 43 +- .../datetime/DateTimeFunctionTest.java | 435 +------- .../sql/expression/datetime/DateTimeTest.java | 30 +- .../expression/datetime/DateTimeTestBase.java | 60 +- .../sql/expression/datetime/MakeDateTest.java | 16 - .../sql/expression/datetime/MakeTimeTest.java | 24 - .../datetime/NowLikeFunctionTest.java | 8 +- .../expression/datetime/TimestampTest.java | 7 +- .../datetime/UnixTwoWayConversionTest.java | 4 +- .../arthmetic/ArithmeticFunctionTest.java | 74 -- .../arthmetic/MathematicalFunctionTest.java | 948 ++---------------- .../operator/arthmetic/UnaryFunctionTest.java | 0 .../BinaryPredicateOperatorTest.java | 317 ------ .../planner/physical/FilterOperatorTest.java | 3 +- docs/user/dql/functions.rst | 281 ++++-- docs/user/ppl/functions/datetime.rst | 18 +- docs/user/ppl/functions/math.rst | 2 + docs/user/ppl/functions/relevance.rst | 7 +- docs/user/ppl/functions/string.rst | 7 +- doctest/build.gradle | 2 +- .../sql/ppl/DateTimeFunctionIT.java | 201 ---- .../opensearch/sql/ppl/NowLikeFunctionIT.java | 198 ++++ .../sql/sql/DateTimeFunctionIT.java | 200 ---- .../opensearch/sql/sql/NowLikeFunctionIT.java | 217 ++++ .../lucene/relevance/RelevanceQuery.java | 4 - ppl/src/main/antlr/OpenSearchPPLParser.g4 | 201 +++- sql/src/main/antlr/OpenSearchSQLParser.g4 | 185 +++- 44 files changed, 1465 insertions(+), 2812 deletions(-) delete mode 100644 core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/UnaryFunctionTest.java create mode 100644 integ-test/src/test/java/org/opensearch/sql/ppl/NowLikeFunctionIT.java create mode 100644 integ-test/src/test/java/org/opensearch/sql/sql/NowLikeFunctionIT.java diff --git a/core/src/main/java/org/opensearch/sql/ast/statement/Explain.java b/core/src/main/java/org/opensearch/sql/ast/statement/Explain.java index d0f2e3b372..1e364d69fd 100644 --- a/core/src/main/java/org/opensearch/sql/ast/statement/Explain.java +++ b/core/src/main/java/org/opensearch/sql/ast/statement/Explain.java @@ -9,12 +9,14 @@ package org.opensearch.sql.ast.statement; import lombok.Data; +import lombok.EqualsAndHashCode; import org.opensearch.sql.ast.AbstractNodeVisitor; /** * Explain Statement. */ @Data +@EqualsAndHashCode(callSuper = false) public class Explain extends Statement { private final Statement statement; diff --git a/core/src/main/java/org/opensearch/sql/ast/tree/Limit.java b/core/src/main/java/org/opensearch/sql/ast/tree/Limit.java index af6936e6a6..f9b8a8feab 100644 --- a/core/src/main/java/org/opensearch/sql/ast/tree/Limit.java +++ b/core/src/main/java/org/opensearch/sql/ast/tree/Limit.java @@ -17,7 +17,7 @@ @RequiredArgsConstructor @Getter @ToString -@EqualsAndHashCode +@EqualsAndHashCode(callSuper = false) public class Limit extends UnresolvedPlan { private UnresolvedPlan child; private final Integer limit; 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 b0c7a02c88..57ce87df47 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 @@ -7,6 +7,7 @@ package org.opensearch.sql.data.model; import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_VARIABLE_NANOS_OPTIONAL; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import com.google.common.base.Objects; import java.time.Instant; @@ -68,7 +69,7 @@ public LocalDateTime datetimeValue() { @Override public Instant timestampValue() { - return ZonedDateTime.of(date, timeValue(), ExprTimestampValue.ZONE).toInstant(); + return ZonedDateTime.of(date, timeValue(), UTC_ZONE_ID).toInstant(); } @Override diff --git a/core/src/main/java/org/opensearch/sql/data/model/ExprDatetimeValue.java b/core/src/main/java/org/opensearch/sql/data/model/ExprDatetimeValue.java index 8a9a544cd9..8d40aaf82c 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 @@ -6,6 +6,9 @@ package org.opensearch.sql.data.model; +import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_WITH_TZ; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; + import com.google.common.base.Objects; import java.time.Instant; import java.time.LocalDate; @@ -13,40 +16,24 @@ import java.time.LocalTime; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; import lombok.RequiredArgsConstructor; import org.opensearch.sql.data.type.ExprCoreType; import org.opensearch.sql.data.type.ExprType; import org.opensearch.sql.exception.SemanticCheckException; + @RequiredArgsConstructor public class ExprDatetimeValue extends AbstractExprValue { private final LocalDateTime datetime; - private static final DateTimeFormatter FORMATTER_VARIABLE_NANOS; - private static final int MIN_FRACTION_SECONDS = 0; - private static final int MAX_FRACTION_SECONDS = 9; - - static { - FORMATTER_VARIABLE_NANOS = new DateTimeFormatterBuilder() - .appendPattern("uuuu-MM-dd HH:mm:ss[xxx]") - .appendFraction( - ChronoField.NANO_OF_SECOND, - MIN_FRACTION_SECONDS, - MAX_FRACTION_SECONDS, - true) - .toFormatter(); - } - /** * Constructor with datetime string as input. */ public ExprDatetimeValue(String datetime) { try { - this.datetime = LocalDateTime.parse(datetime, FORMATTER_VARIABLE_NANOS); + this.datetime = LocalDateTime.parse(datetime, DATE_TIME_FORMATTER_WITH_TZ); } catch (DateTimeParseException e) { throw new SemanticCheckException(String.format("datetime:%s in unsupported format, please " + "use yyyy-MM-dd HH:mm:ss[.SSSSSSSSS]", datetime)); @@ -70,7 +57,7 @@ public LocalTime timeValue() { @Override public Instant timestampValue() { - return ZonedDateTime.of(datetime, ExprTimestampValue.ZONE).toInstant(); + return ZonedDateTime.of(datetime, UTC_ZONE_ID).toInstant(); } @Override diff --git a/core/src/main/java/org/opensearch/sql/data/model/ExprTimeValue.java b/core/src/main/java/org/opensearch/sql/data/model/ExprTimeValue.java index 15bd1d7dae..db5bf7cb52 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 @@ -8,6 +8,7 @@ import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME; import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_VARIABLE_NANOS_OPTIONAL; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import java.time.Instant; import java.time.LocalDate; @@ -66,7 +67,7 @@ public LocalDateTime datetimeValue(FunctionProperties functionProperties) { } public Instant timestampValue(FunctionProperties functionProperties) { - return ZonedDateTime.of(dateValue(functionProperties), timeValue(), ExprTimestampValue.ZONE) + return ZonedDateTime.of(dateValue(functionProperties), timeValue(), UTC_ZONE_ID) .toInstant(); } 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 7e6e75ed0d..d15cee5e71 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 @@ -8,12 +8,12 @@ import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_VARIABLE_NANOS; import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_WITHOUT_NANO; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneId; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoUnit; import java.util.Objects; @@ -27,10 +27,6 @@ */ @RequiredArgsConstructor public class ExprTimestampValue extends AbstractExprValue { - /** - * todo. only support UTC now. - */ - public static final ZoneId ZONE = ZoneId.of("UTC"); private final Instant timestamp; @@ -40,7 +36,7 @@ public class ExprTimestampValue extends AbstractExprValue { public ExprTimestampValue(String timestamp) { try { this.timestamp = LocalDateTime.parse(timestamp, DATE_TIME_FORMATTER_VARIABLE_NANOS) - .atZone(ZONE) + .atZone(UTC_ZONE_ID) .toInstant(); } catch (DateTimeParseException e) { throw new SemanticCheckException(String.format("timestamp:%s in unsupported format, please " @@ -51,9 +47,9 @@ public ExprTimestampValue(String timestamp) { @Override public String value() { - return timestamp.getNano() == 0 ? DATE_TIME_FORMATTER_WITHOUT_NANO.withZone(ZONE) + return timestamp.getNano() == 0 ? DATE_TIME_FORMATTER_WITHOUT_NANO.withZone(UTC_ZONE_ID) .format(timestamp.truncatedTo(ChronoUnit.SECONDS)) - : DATE_TIME_FORMATTER_VARIABLE_NANOS.withZone(ZONE).format(timestamp); + : DATE_TIME_FORMATTER_VARIABLE_NANOS.withZone(UTC_ZONE_ID).format(timestamp); } @Override @@ -68,17 +64,17 @@ public Instant timestampValue() { @Override public LocalDate dateValue() { - return timestamp.atZone(ZONE).toLocalDate(); + return timestamp.atZone(UTC_ZONE_ID).toLocalDate(); } @Override public LocalTime timeValue() { - return timestamp.atZone(ZONE).toLocalTime(); + return timestamp.atZone(UTC_ZONE_ID).toLocalTime(); } @Override public LocalDateTime datetimeValue() { - return timestamp.atZone(ZONE).toLocalDateTime(); + return timestamp.atZone(UTC_ZONE_ID).toLocalDateTime(); } @Override @@ -93,12 +89,12 @@ public String toString() { @Override public int compare(ExprValue other) { - return timestamp.compareTo(other.timestampValue().atZone(ZONE).toInstant()); + return timestamp.compareTo(other.timestampValue().atZone(UTC_ZONE_ID).toInstant()); } @Override public boolean equal(ExprValue other) { - return timestamp.equals(other.timestampValue().atZone(ZONE).toInstant()); + return timestamp.equals(other.timestampValue().atZone(UTC_ZONE_ID).toInstant()); } @Override 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 f9ef20e305..3f1897e483 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -501,7 +501,6 @@ public static FunctionExpression to_seconds(Expression... expressions) { return to_seconds(FunctionProperties.None, expressions); } - public static FunctionExpression week( FunctionProperties functionProperties, Expression... expressions) { return compile(functionProperties, BuiltinFunctionName.WEEK, expressions); diff --git a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java index ae35b4b41f..cd5ef23d1c 100644 --- a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java @@ -43,6 +43,7 @@ import static org.opensearch.sql.utils.DateTimeFormatters.SHORT_DATE_LENGTH; import static org.opensearch.sql.utils.DateTimeFormatters.SINGLE_DIGIT_MONTH_DATE_LENGTH; import static org.opensearch.sql.utils.DateTimeFormatters.SINGLE_DIGIT_YEAR_DATE_LENGTH; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import static org.opensearch.sql.utils.DateTimeUtils.extractDate; import static org.opensearch.sql.utils.DateTimeUtils.extractDateTime; @@ -67,14 +68,12 @@ import java.time.format.TextStyle; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAmount; -import java.util.Arrays; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; import lombok.experimental.UtilityClass; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.opensearch.sql.data.model.ExprDateValue; import org.opensearch.sql.data.model.ExprDatetimeValue; @@ -84,11 +83,9 @@ import org.opensearch.sql.data.model.ExprNullValue; import org.opensearch.sql.data.model.ExprStringValue; import org.opensearch.sql.data.model.ExprTimeValue; -import org.opensearch.sql.data.model.ExprTimestampValue; import org.opensearch.sql.data.model.ExprValue; import org.opensearch.sql.data.type.ExprCoreType; import org.opensearch.sql.exception.ExpressionEvaluationException; -import org.opensearch.sql.exception.SemanticCheckException; import org.opensearch.sql.expression.function.BuiltinFunctionName; import org.opensearch.sql.expression.function.BuiltinFunctionRepository; import org.opensearch.sql.expression.function.DefaultFunctionResolver; @@ -191,6 +188,7 @@ public void register(BuiltinFunctionRepository repository) { repository.register(datediff()); repository.register(datetime()); repository.register(date_add()); + repository.register(date_format()); repository.register(date_sub()); repository.register(day()); repository.register(dayName()); @@ -236,13 +234,12 @@ public void register(BuiltinFunctionRepository repository) { repository.register(timestamp()); repository.register(timestampadd()); repository.register(timestampdiff()); - repository.register(utc_date()); - repository.register(utc_time()); - repository.register(utc_timestamp()); - repository.register(date_format()); repository.register(to_days()); repository.register(to_seconds()); repository.register(unix_timestamp()); + repository.register(utc_date()); + repository.register(utc_time()); + repository.register(utc_timestamp()); repository.register(week(BuiltinFunctionName.WEEK)); repository.register(week(BuiltinFunctionName.WEEKOFYEAR)); repository.register(week(BuiltinFunctionName.WEEK_OF_YEAR)); @@ -1286,7 +1283,6 @@ private ExprValue exprConvertTZ(ExprValue startingDateTime, ExprValue fromTz, Ex return new ExprDatetimeValue( zonedDateTime.withZoneSameInstant(convertedToTz).toLocalDateTime()); - // Catches exception for invalid timezones. // ex. "+0:00" is an invalid timezone and would result in this exception being thrown. } catch (ExpressionEvaluationException | DateTimeException e) { @@ -1334,7 +1330,6 @@ private ExprValue exprDateDiff(FunctionProperties functionProperties, private ExprValue exprDateTime(ExprValue dateTime, ExprValue timeZone) { String defaultTimeZone = TimeZone.getDefault().getID(); - try { LocalDateTime ldtFormatted = LocalDateTime.parse(dateTime.stringValue(), DATE_TIME_FORMATTER_STRICT_WITH_TZ); @@ -1490,7 +1485,7 @@ private ExprValue exprFromUnixTime(ExprValue time) { private LocalDateTime exprFromUnixTimeImpl(ExprValue time) { return LocalDateTime.ofInstant( Instant.ofEpochSecond((long)Math.floor(time.doubleValue())), - ZoneId.of("UTC")) + UTC_ZONE_ID) .withNano((int)((time.doubleValue() % 1) * 1E9)); } @@ -1994,7 +1989,7 @@ private ExprValue exprUtcTime(FunctionProperties functionProperties) { */ private ExprValue exprUtcTimeStamp(FunctionProperties functionProperties) { var zdt = ZonedDateTime.now(functionProperties.getQueryStartClock()) - .withZoneSameInstant(ZoneId.of("UTC")); + .withZoneSameInstant(UTC_ZONE_ID); return new ExprDatetimeValue(zdt.toLocalDateTime()); } diff --git a/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/ArithmeticFunction.java b/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/ArithmeticFunction.java index cfa952ffe7..7130ac105a 100644 --- a/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/ArithmeticFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/ArithmeticFunction.java @@ -12,6 +12,9 @@ import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; import static org.opensearch.sql.data.type.ExprCoreType.LONG; import static org.opensearch.sql.data.type.ExprCoreType.SHORT; +import static org.opensearch.sql.expression.function.FunctionDSL.define; +import static org.opensearch.sql.expression.function.FunctionDSL.impl; +import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandling; import lombok.experimental.UtilityClass; import org.opensearch.sql.data.model.ExprByteValue; @@ -24,7 +27,6 @@ import org.opensearch.sql.expression.function.BuiltinFunctionName; import org.opensearch.sql.expression.function.BuiltinFunctionRepository; import org.opensearch.sql.expression.function.DefaultFunctionResolver; -import org.opensearch.sql.expression.function.FunctionDSL; import org.opensearch.sql.expression.function.FunctionName; /** @@ -64,33 +66,25 @@ public static void register(BuiltinFunctionRepository repository) { * -> wider type between types of x and y */ private static DefaultFunctionResolver addBase(FunctionName functionName) { - return FunctionDSL.define(functionName, - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() + v2.byteValue())), - BYTE, BYTE, BYTE), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprShortValue(v1.shortValue() + v2.shortValue())), - SHORT, SHORT, SHORT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprIntegerValue(Math.addExact(v1.integerValue(), - v2.integerValue()))), - INTEGER, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprLongValue( - Math.addExact(v1.longValue(), v2.longValue()))), - LONG, LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprFloatValue(v1.floatValue() + v2.floatValue())), - FLOAT, FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprDoubleValue(v1.doubleValue() + v2.doubleValue())), - DOUBLE, DOUBLE, DOUBLE) + return define(functionName, + impl(nullMissingHandling( + (v1, v2) -> new ExprByteValue(v1.byteValue() + v2.byteValue())), + BYTE, BYTE, BYTE), + impl(nullMissingHandling( + (v1, v2) -> new ExprShortValue(v1.shortValue() + v2.shortValue())), + SHORT, SHORT, SHORT), + impl(nullMissingHandling( + (v1, v2) -> new ExprIntegerValue(Math.addExact(v1.integerValue(), v2.integerValue()))), + INTEGER, INTEGER, INTEGER), + impl(nullMissingHandling( + (v1, v2) -> new ExprLongValue(Math.addExact(v1.longValue(), v2.longValue()))), + LONG, LONG, LONG), + impl(nullMissingHandling( + (v1, v2) -> new ExprFloatValue(v1.floatValue() + v2.floatValue())), + FLOAT, FLOAT, FLOAT), + impl(nullMissingHandling( + (v1, v2) -> new ExprDoubleValue(v1.doubleValue() + v2.doubleValue())), + DOUBLE, DOUBLE, DOUBLE) ); } @@ -110,36 +104,30 @@ private static DefaultFunctionResolver addFunction() { * -> wider type between types of x and y */ private static DefaultFunctionResolver divideBase(FunctionName functionName) { - return FunctionDSL.define(functionName, - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() / v2.byteValue())), - BYTE, BYTE, BYTE), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : - new ExprShortValue(v1.shortValue() / v2.shortValue())), - SHORT, SHORT, SHORT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.integerValue() == 0 ? ExprNullValue.of() : - new ExprIntegerValue(v1.integerValue() / v2.integerValue())), - INTEGER, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.longValue() == 0 ? ExprNullValue.of() : - new ExprLongValue(v1.longValue() / v2.longValue())), - LONG, LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.floatValue() == 0 ? ExprNullValue.of() : - new ExprFloatValue(v1.floatValue() / v2.floatValue())), - FLOAT, FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.doubleValue() == 0 ? ExprNullValue.of() : - new ExprDoubleValue(v1.doubleValue() / v2.doubleValue())), - DOUBLE, DOUBLE, DOUBLE) + return define(functionName, + impl(nullMissingHandling( + (v1, v2) -> new ExprByteValue(v1.byteValue() / v2.byteValue())), + BYTE, BYTE, BYTE), + impl(nullMissingHandling( + (v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprShortValue(v1.shortValue() / v2.shortValue())), + SHORT, SHORT, SHORT), + impl(nullMissingHandling( + (v1, v2) -> v2.integerValue() == 0 ? ExprNullValue.of() : + new ExprIntegerValue(v1.integerValue() / v2.integerValue())), + INTEGER, INTEGER, INTEGER), + impl(nullMissingHandling( + (v1, v2) -> v2.longValue() == 0 ? ExprNullValue.of() : + new ExprLongValue(v1.longValue() / v2.longValue())), + LONG, LONG, LONG), + impl(nullMissingHandling( + (v1, v2) -> v2.floatValue() == 0 ? ExprNullValue.of() : + new ExprFloatValue(v1.floatValue() / v2.floatValue())), + FLOAT, FLOAT, FLOAT), + impl(nullMissingHandling( + (v1, v2) -> v2.doubleValue() == 0 ? ExprNullValue.of() : + new ExprDoubleValue(v1.doubleValue() / v2.doubleValue())), + DOUBLE, DOUBLE, DOUBLE) ); } @@ -159,35 +147,29 @@ private static DefaultFunctionResolver divideFunction() { * -> wider type between types of x and y */ private static DefaultFunctionResolver modulusBase(FunctionName functionName) { - return FunctionDSL.define(functionName, - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() % v2.byteValue())), + return define(functionName, + impl(nullMissingHandling( + (v1, v2) -> new ExprByteValue(v1.byteValue() % v2.byteValue())), BYTE, BYTE, BYTE), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : - new ExprShortValue(v1.shortValue() % v2.shortValue())), + impl(nullMissingHandling( + (v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprShortValue(v1.shortValue() % v2.shortValue())), SHORT, SHORT, SHORT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.integerValue() == 0 ? ExprNullValue.of() : - new ExprIntegerValue(v1.integerValue() % v2.integerValue())), + impl(nullMissingHandling( + (v1, v2) -> v2.integerValue() == 0 ? ExprNullValue.of() : + new ExprIntegerValue(v1.integerValue() % v2.integerValue())), INTEGER, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.longValue() == 0 ? ExprNullValue.of() : - new ExprLongValue(v1.longValue() % v2.longValue())), + impl(nullMissingHandling( + (v1, v2) -> v2.longValue() == 0 ? ExprNullValue.of() : + new ExprLongValue(v1.longValue() % v2.longValue())), LONG, LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.floatValue() == 0 ? ExprNullValue.of() : - new ExprFloatValue(v1.floatValue() % v2.floatValue())), + impl(nullMissingHandling( + (v1, v2) -> v2.floatValue() == 0 ? ExprNullValue.of() : + new ExprFloatValue(v1.floatValue() % v2.floatValue())), FLOAT, FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.doubleValue() == 0 ? ExprNullValue.of() : - new ExprDoubleValue(v1.doubleValue() % v2.doubleValue())), + impl(nullMissingHandling( + (v1, v2) -> v2.doubleValue() == 0 ? ExprNullValue.of() : + new ExprDoubleValue(v1.doubleValue() % v2.doubleValue())), DOUBLE, DOUBLE, DOUBLE) ); } @@ -212,32 +194,25 @@ private static DefaultFunctionResolver modulusFunction() { * -> wider type between types of x and y */ private static DefaultFunctionResolver multiplyBase(FunctionName functionName) { - return FunctionDSL.define(functionName, - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() * v2.byteValue())), + return define(functionName, + impl(nullMissingHandling( + (v1, v2) -> new ExprByteValue(v1.byteValue() * v2.byteValue())), BYTE, BYTE, BYTE), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprShortValue(v1.shortValue() * v2.shortValue())), + impl(nullMissingHandling( + (v1, v2) -> new ExprShortValue(v1.shortValue() * v2.shortValue())), SHORT, SHORT, SHORT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprIntegerValue(Math.multiplyExact(v1.integerValue(), - v2.integerValue()))), + impl(nullMissingHandling( + (v1, v2) -> new ExprIntegerValue(Math.multiplyExact(v1.integerValue(), + v2.integerValue()))), INTEGER, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprLongValue( - Math.multiplyExact(v1.longValue(), v2.longValue()))), + impl(nullMissingHandling( + (v1, v2) -> new ExprLongValue(Math.multiplyExact(v1.longValue(), v2.longValue()))), LONG, LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprFloatValue(v1.floatValue() * v2.floatValue())), + impl(nullMissingHandling( + (v1, v2) -> new ExprFloatValue(v1.floatValue() * v2.floatValue())), FLOAT, FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprDoubleValue(v1.doubleValue() * v2.doubleValue())), + impl(nullMissingHandling( + (v1, v2) -> new ExprDoubleValue(v1.doubleValue() * v2.doubleValue())), DOUBLE, DOUBLE, DOUBLE) ); } @@ -258,32 +233,25 @@ private static DefaultFunctionResolver multiplyFunction() { * -> wider type between types of x and y */ private static DefaultFunctionResolver subtractBase(FunctionName functionName) { - return FunctionDSL.define(functionName, - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() - v2.byteValue())), + return define(functionName, + impl(nullMissingHandling( + (v1, v2) -> new ExprByteValue(v1.byteValue() - v2.byteValue())), BYTE, BYTE, BYTE), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprShortValue(v1.shortValue() - v2.shortValue())), + impl(nullMissingHandling( + (v1, v2) -> new ExprShortValue(v1.shortValue() - v2.shortValue())), SHORT, SHORT, SHORT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprIntegerValue(Math.subtractExact(v1.integerValue(), - v2.integerValue()))), + impl(nullMissingHandling( + (v1, v2) -> new ExprIntegerValue(Math.subtractExact(v1.integerValue(), + v2.integerValue()))), INTEGER, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprLongValue( - Math.subtractExact(v1.longValue(), v2.longValue()))), + impl(nullMissingHandling( + (v1, v2) -> new ExprLongValue(Math.subtractExact(v1.longValue(), v2.longValue()))), LONG, LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprFloatValue(v1.floatValue() - v2.floatValue())), + impl(nullMissingHandling( + (v1, v2) -> new ExprFloatValue(v1.floatValue() - v2.floatValue())), FLOAT, FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprDoubleValue(v1.doubleValue() - v2.doubleValue())), + impl(nullMissingHandling( + (v1, v2) -> new ExprDoubleValue(v1.doubleValue() - v2.doubleValue())), DOUBLE, DOUBLE, DOUBLE) ); } @@ -295,4 +263,4 @@ private static DefaultFunctionResolver subtract() { private static DefaultFunctionResolver subtractFunction() { return subtractBase(BuiltinFunctionName.SUBTRACTFUNCTION.getName()); } -} +} \ No newline at end of file diff --git a/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java b/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java index 73257cf988..810d292ca2 100644 --- a/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java @@ -13,6 +13,9 @@ import static org.opensearch.sql.data.type.ExprCoreType.LONG; import static org.opensearch.sql.data.type.ExprCoreType.SHORT; import static org.opensearch.sql.data.type.ExprCoreType.STRING; +import static org.opensearch.sql.expression.function.FunctionDSL.define; +import static org.opensearch.sql.expression.function.FunctionDSL.impl; +import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandling; import com.google.common.collect.ImmutableList; import java.math.BigDecimal; @@ -39,7 +42,6 @@ import org.opensearch.sql.expression.function.BuiltinFunctionRepository; import org.opensearch.sql.expression.function.DefaultFunctionResolver; import org.opensearch.sql.expression.function.FunctionBuilder; -import org.opensearch.sql.expression.function.FunctionDSL; import org.opensearch.sql.expression.function.FunctionName; import org.opensearch.sql.expression.function.FunctionSignature; import org.opensearch.sql.expression.function.SerializableFunction; @@ -53,11 +55,19 @@ public class MathematicalFunction { */ public static void register(BuiltinFunctionRepository repository) { repository.register(abs()); + repository.register(acos()); + repository.register(asin()); + repository.register(atan()); + repository.register(atan2()); repository.register(cbrt()); repository.register(ceil()); repository.register(ceiling()); repository.register(conv()); + repository.register(cos()); + repository.register(cosh()); + repository.register(cot()); repository.register(crc32()); + repository.register(degrees()); repository.register(euler()); repository.register(exp()); repository.register(expm1()); @@ -66,28 +76,21 @@ public static void register(BuiltinFunctionRepository repository) { repository.register(log()); repository.register(log10()); repository.register(log2()); + repository.register(mod()); + repository.register(pi()); repository.register(pow()); repository.register(power()); + repository.register(radians()); + repository.register(rand()); repository.register(rint()); repository.register(round()); repository.register(sign()); repository.register(signum()); + repository.register(sin()); repository.register(sinh()); repository.register(sqrt()); - repository.register(truncate()); - repository.register(pi()); - repository.register(rand()); - repository.register(acos()); - repository.register(asin()); - repository.register(atan()); - repository.register(atan2()); - repository.register(cos()); - repository.register(cosh()); - repository.register(cot()); - repository.register(degrees()); - repository.register(radians()); - repository.register(sin()); repository.register(tan()); + repository.register(truncate()); } /** @@ -101,10 +104,8 @@ public static void register(BuiltinFunctionRepository repository) { private static DefaultFunctionResolver baseMathFunction( FunctionName functionName, SerializableFunction formula, ExprCoreType returnType) { - return FunctionDSL.define(functionName, - ExprCoreType.numberTypes().stream().map(type -> FunctionDSL.impl( - FunctionDSL.nullMissingHandling(formula), - returnType, type)).collect(Collectors.toList())); + return define(functionName, ExprCoreType.numberTypes().stream().map(type -> + impl(nullMissingHandling(formula), returnType, type)).collect(Collectors.toList())); } /** @@ -112,24 +113,18 @@ private static DefaultFunctionResolver baseMathFunction( * LONG FLOAT -> FLOAT DOUBLE -> DOUBLE */ private static DefaultFunctionResolver abs() { - return FunctionDSL.define(BuiltinFunctionName.ABS.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprByteValue(Math.abs(v.byteValue()))), + return define(BuiltinFunctionName.ABS.getName(), + impl(nullMissingHandling(v -> new ExprByteValue(Math.abs(v.byteValue()))), BYTE, BYTE), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprShortValue(Math.abs(v.shortValue()))), + impl(nullMissingHandling(v -> new ExprShortValue(Math.abs(v.shortValue()))), SHORT, SHORT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprIntegerValue(Math.abs(v.integerValue()))), + impl(nullMissingHandling(v -> new ExprIntegerValue(Math.abs(v.integerValue()))), INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprLongValue(Math.abs(v.longValue()))), + impl(nullMissingHandling(v -> new ExprLongValue(Math.abs(v.longValue()))), LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprFloatValue(Math.abs(v.floatValue()))), + impl(nullMissingHandling(v -> new ExprFloatValue(Math.abs(v.floatValue()))), FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprDoubleValue(Math.abs(v.doubleValue()))), + impl(nullMissingHandling(v -> new ExprDoubleValue(Math.abs(v.doubleValue()))), DOUBLE, DOUBLE) ); } @@ -139,17 +134,15 @@ private static DefaultFunctionResolver abs() { * to The supported signature of ceil/ceiling function is DOUBLE -> INTEGER */ private static DefaultFunctionResolver ceil() { - return FunctionDSL.define(BuiltinFunctionName.CEIL.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprLongValue(Math.ceil(v.doubleValue()))), + return define(BuiltinFunctionName.CEIL.getName(), + impl(nullMissingHandling(v -> new ExprLongValue(Math.ceil(v.doubleValue()))), LONG, DOUBLE) ); } private static DefaultFunctionResolver ceiling() { - return FunctionDSL.define(BuiltinFunctionName.CEILING.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprLongValue(Math.ceil(v.doubleValue()))), + return define(BuiltinFunctionName.CEILING.getName(), + impl(nullMissingHandling(v -> new ExprLongValue(Math.ceil(v.doubleValue()))), LONG, DOUBLE) ); } @@ -162,18 +155,14 @@ private static DefaultFunctionResolver ceiling() { * (INTEGER, INTEGER, INTEGER) -> STRING */ private static DefaultFunctionResolver conv() { - return FunctionDSL.define(BuiltinFunctionName.CONV.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling((x, a, b) -> new ExprStringValue( - Integer.toString(Integer.parseInt(x.stringValue(), a.integerValue()), - b.integerValue()) - )), + return define(BuiltinFunctionName.CONV.getName(), + impl(nullMissingHandling((x, a, b) -> new ExprStringValue( + Integer.toString(Integer.parseInt(x.stringValue(), a.integerValue()), + b.integerValue()))), STRING, STRING, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling((x, a, b) -> new ExprStringValue( - Integer.toString(Integer.parseInt(x.integerValue().toString(), a.integerValue()), - b.integerValue()) - )), + impl(nullMissingHandling((x, a, b) -> new ExprStringValue( + Integer.toString(Integer.parseInt(x.integerValue().toString(), a.integerValue()), + b.integerValue()))), STRING, INTEGER, INTEGER, INTEGER) ); } @@ -185,14 +174,13 @@ private static DefaultFunctionResolver conv() { * STRING -> LONG */ private static DefaultFunctionResolver crc32() { - return FunctionDSL.define(BuiltinFunctionName.CRC32.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> { - CRC32 crc = new CRC32(); - crc.update(v.stringValue().getBytes()); - return new ExprLongValue(crc.getValue()); - }), - LONG, STRING) + return define(BuiltinFunctionName.CRC32.getName(), + impl(nullMissingHandling(v -> { + CRC32 crc = new CRC32(); + crc.update(v.stringValue().getBytes()); + return new ExprLongValue(crc.getValue()); + }), + LONG, STRING) ); } @@ -202,8 +190,8 @@ private static DefaultFunctionResolver crc32() { * () -> DOUBLE */ private static DefaultFunctionResolver euler() { - return FunctionDSL.define(BuiltinFunctionName.E.getName(), - FunctionDSL.impl(() -> new ExprDoubleValue(Math.E), DOUBLE) + return define(BuiltinFunctionName.E.getName(), + impl(() -> new ExprDoubleValue(Math.E), DOUBLE) ); } @@ -230,9 +218,8 @@ private static DefaultFunctionResolver expm1() { * The supported signature of floor function is DOUBLE -> INTEGER */ private static DefaultFunctionResolver floor() { - return FunctionDSL.define(BuiltinFunctionName.FLOOR.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling(v -> new ExprLongValue(Math.floor(v.doubleValue()))), + return define(BuiltinFunctionName.FLOOR.getName(), + impl(nullMissingHandling(v -> new ExprLongValue(Math.floor(v.doubleValue()))), LONG, DOUBLE) ); } @@ -258,23 +245,21 @@ private static DefaultFunctionResolver log() { // build unary log(x), SHORT/INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE for (ExprType type : ExprCoreType.numberTypes()) { - builder.add(FunctionDSL.impl(FunctionDSL - .nullMissingHandling(v -> v.doubleValue() <= 0 ? ExprNullValue.of() : - new ExprDoubleValue(Math.log(v.doubleValue()))), + builder.add(impl(nullMissingHandling(v -> v.doubleValue() <= 0 ? ExprNullValue.of() : + new ExprDoubleValue(Math.log(v.doubleValue()))), DOUBLE, type)); } // build binary function log(b, x) for (ExprType baseType : ExprCoreType.numberTypes()) { for (ExprType numberType : ExprCoreType.numberTypes()) { - builder.add(FunctionDSL.impl(FunctionDSL - .nullMissingHandling((b, x) -> b.doubleValue() <= 0 || x.doubleValue() <= 0 - ? ExprNullValue.of() : new ExprDoubleValue( + builder.add(impl(nullMissingHandling((b, x) -> b.doubleValue() <= 0 || x.doubleValue() <= 0 + ? ExprNullValue.of() : new ExprDoubleValue( Math.log(x.doubleValue()) / Math.log(b.doubleValue()))), DOUBLE, baseType, numberType)); } } - return FunctionDSL.define(BuiltinFunctionName.LOG.getName(), builder.build()); + return define(BuiltinFunctionName.LOG.getName(), builder.build()); } @@ -298,14 +283,44 @@ private static DefaultFunctionResolver log2() { new ExprDoubleValue(Math.log(v.doubleValue()) / Math.log(2)), DOUBLE); } + /** + * Definition of mod(x, y) function. + * Calculate the remainder of x divided by y + * The supported signature of mod function is + * (x: INTEGER/LONG/FLOAT/DOUBLE, y: INTEGER/LONG/FLOAT/DOUBLE) + * -> wider type between types of x and y + */ + private static DefaultFunctionResolver mod() { + return define(BuiltinFunctionName.MOD.getName(), + impl(nullMissingHandling((v1, v2) -> v2.byteValue() == 0 ? ExprNullValue.of() : + new ExprByteValue(v1.byteValue() % v2.byteValue())), + BYTE, BYTE, BYTE), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprShortValue(v1.shortValue() % v2.shortValue())), + SHORT, SHORT, SHORT), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprIntegerValue(Math.floorMod(v1.integerValue(), v2.integerValue()))), + INTEGER, INTEGER, INTEGER), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprLongValue(Math.floorMod(v1.longValue(), v2.longValue()))), + LONG, LONG, LONG), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprFloatValue(v1.floatValue() % v2.floatValue())), + FLOAT, FLOAT, FLOAT), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprDoubleValue(v1.doubleValue() % v2.doubleValue())), + DOUBLE, DOUBLE, DOUBLE) + ); + } + /** * Definition of pi() function. * Get the value of pi. * () -> DOUBLE */ private static DefaultFunctionResolver pi() { - return FunctionDSL.define(BuiltinFunctionName.PI.getName(), - FunctionDSL.impl(() -> new ExprDoubleValue(Math.PI), DOUBLE) + return define(BuiltinFunctionName.PI.getName(), + impl(() -> new ExprDoubleValue(Math.PI), DOUBLE) ); } @@ -319,39 +334,34 @@ private static DefaultFunctionResolver pi() { * (DOUBLE, DOUBLE) -> DOUBLE */ private static DefaultFunctionResolver pow() { - return FunctionDSL.define(BuiltinFunctionName.POW.getName(), powerFunctionImpl()); + return define(BuiltinFunctionName.POW.getName(), powerFunctionImpl()); } private static DefaultFunctionResolver power() { - return FunctionDSL.define(BuiltinFunctionName.POWER.getName(), powerFunctionImpl()); + return define(BuiltinFunctionName.POWER.getName(), powerFunctionImpl()); } private List>> powerFunctionImpl() { - return Arrays.asList(FunctionDSL.impl( - FunctionDSL.nullMissingHandling( + return Arrays.asList( + impl(nullMissingHandling( (v1, v2) -> new ExprDoubleValue(Math.pow(v1.shortValue(), v2.shortValue()))), - DOUBLE, SHORT, SHORT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprDoubleValue(Math.pow(v1.integerValue(), - v2.integerValue()))), + DOUBLE, SHORT, SHORT), + impl(nullMissingHandling( + (v1, v2) -> new ExprDoubleValue(Math.pow(v1.integerValue(), v2.integerValue()))), DOUBLE, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprDoubleValue(Math.pow(v1.longValue(), v2.longValue()))), + impl(nullMissingHandling( + (v1, v2) -> new ExprDoubleValue(Math.pow(v1.longValue(), v2.longValue()))), DOUBLE, LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v1.floatValue() <= 0 && v2.floatValue() - != Math.floor(v2.floatValue()) ? ExprNullValue.of() : - new ExprDoubleValue(Math.pow(v1.floatValue(), v2.floatValue()))), + impl(nullMissingHandling( + (v1, v2) -> v1.floatValue() <= 0 && v2.floatValue() != Math.floor(v2.floatValue()) + ? ExprNullValue.of() : + new ExprDoubleValue(Math.pow(v1.floatValue(), v2.floatValue()))), DOUBLE, FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v1.doubleValue() <= 0 && v2.doubleValue() - != Math.floor(v2.doubleValue()) ? ExprNullValue.of() : - new ExprDoubleValue(Math.pow(v1.doubleValue(), v2.doubleValue()))), + impl(nullMissingHandling( + (v1, v2) -> v1.doubleValue() <= 0 && v2.doubleValue() != Math.floor(v2.doubleValue()) + ? ExprNullValue.of() : + new ExprDoubleValue(Math.pow(v1.doubleValue(), v2.doubleValue()))), DOUBLE, DOUBLE, DOUBLE)); } @@ -365,11 +375,10 @@ FunctionBuilder>>> powerFunctionImpl() { * ([INTEGER]) -> FLOAT */ private static DefaultFunctionResolver rand() { - return FunctionDSL.define(BuiltinFunctionName.RAND.getName(), - FunctionDSL.impl(() -> new ExprFloatValue(new Random().nextFloat()), FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - v -> new ExprFloatValue(new Random(v.integerValue()).nextFloat())), FLOAT, INTEGER) + return define(BuiltinFunctionName.RAND.getName(), + impl(() -> new ExprFloatValue(new Random().nextFloat()), FLOAT), + impl(nullMissingHandling( + v -> new ExprFloatValue(new Random(v.integerValue()).nextFloat())), FLOAT, INTEGER) ); } @@ -394,47 +403,30 @@ private static DefaultFunctionResolver rint() { * (x: DOUBLE [, y: INTEGER]) -> DOUBLE */ private static DefaultFunctionResolver round() { - return FunctionDSL.define(BuiltinFunctionName.ROUND.getName(), + return define(BuiltinFunctionName.ROUND.getName(), // rand(x) - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - v -> new ExprLongValue((long) Math.round(v.integerValue()))), + impl(nullMissingHandling(v -> new ExprLongValue((long) Math.round(v.integerValue()))), LONG, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - v -> new ExprLongValue((long) Math.round(v.longValue()))), + impl(nullMissingHandling(v -> new ExprLongValue((long) Math.round(v.longValue()))), LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - v -> new ExprDoubleValue((double) Math.round(v.floatValue()))), + impl(nullMissingHandling(v -> new ExprDoubleValue((double) Math.round(v.floatValue()))), DOUBLE, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - v -> new ExprDoubleValue(new BigDecimal(v.doubleValue()).setScale(0, - RoundingMode.HALF_UP).doubleValue())), + impl(nullMissingHandling(v -> new ExprDoubleValue(new BigDecimal(v.doubleValue()) + .setScale(0, RoundingMode.HALF_UP).doubleValue())), DOUBLE, DOUBLE), // rand(x, d) - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (x, d) -> new ExprLongValue( - new BigDecimal(x.integerValue()).setScale(d.integerValue(), - RoundingMode.HALF_UP).longValue())), + impl(nullMissingHandling((x, d) -> new ExprLongValue(new BigDecimal(x.integerValue()) + .setScale(d.integerValue(), RoundingMode.HALF_UP).longValue())), LONG, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (x, d) -> new ExprLongValue(new BigDecimal(x.longValue()).setScale(d.integerValue(), - RoundingMode.HALF_UP).longValue())), + impl(nullMissingHandling((x, d) -> new ExprLongValue(new BigDecimal(x.longValue()) + .setScale(d.integerValue(), RoundingMode.HALF_UP).longValue())), LONG, LONG, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (x, d) -> new ExprDoubleValue(new BigDecimal(x.floatValue()) - .setScale(d.integerValue(), RoundingMode.HALF_UP).doubleValue())), + impl(nullMissingHandling((x, d) -> new ExprDoubleValue(new BigDecimal(x.floatValue()) + .setScale(d.integerValue(), RoundingMode.HALF_UP).doubleValue())), DOUBLE, FLOAT, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (x, d) -> new ExprDoubleValue(new BigDecimal(x.doubleValue()) - .setScale(d.integerValue(), RoundingMode.HALF_UP).doubleValue())), + impl(nullMissingHandling((x, d) -> new ExprDoubleValue(new BigDecimal(x.doubleValue()) + .setScale(d.integerValue(), RoundingMode.HALF_UP).doubleValue())), DOUBLE, DOUBLE, INTEGER)); } @@ -506,30 +498,18 @@ private static DefaultFunctionResolver cbrt() { * (x: DOUBLE, y: INTEGER) -> DOUBLE */ private static DefaultFunctionResolver truncate() { - return FunctionDSL.define(BuiltinFunctionName.TRUNCATE.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (x, y) -> new ExprLongValue( - BigDecimal.valueOf(x.integerValue()).setScale(y.integerValue(), - RoundingMode.DOWN).longValue())), + return define(BuiltinFunctionName.TRUNCATE.getName(), + impl(nullMissingHandling((x, y) -> new ExprLongValue(BigDecimal.valueOf(x.integerValue()) + .setScale(y.integerValue(), RoundingMode.DOWN).longValue())), LONG, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (x, y) -> new ExprLongValue( - BigDecimal.valueOf(x.longValue()).setScale(y.integerValue(), - RoundingMode.DOWN).longValue())), + impl(nullMissingHandling((x, y) -> new ExprLongValue(BigDecimal.valueOf(x.longValue()) + .setScale(y.integerValue(), RoundingMode.DOWN).longValue())), LONG, LONG, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (x, y) -> new ExprDoubleValue( - BigDecimal.valueOf(x.floatValue()).setScale(y.integerValue(), - RoundingMode.DOWN).doubleValue())), + impl(nullMissingHandling((x, y) -> new ExprDoubleValue(BigDecimal.valueOf(x.floatValue()) + .setScale(y.integerValue(), RoundingMode.DOWN).doubleValue())), DOUBLE, FLOAT, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (x, y) -> new ExprDoubleValue( - BigDecimal.valueOf(x.doubleValue()).setScale(y.integerValue(), - RoundingMode.DOWN).doubleValue())), + impl(nullMissingHandling((x, y) -> new ExprDoubleValue(BigDecimal.valueOf(x.doubleValue()) + .setScale(y.integerValue(), RoundingMode.DOWN).doubleValue())), DOUBLE, DOUBLE, INTEGER)); } @@ -541,9 +521,9 @@ private static DefaultFunctionResolver truncate() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver acos() { - return FunctionDSL.define(BuiltinFunctionName.ACOS.getName(), + return define(BuiltinFunctionName.ACOS.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> v.doubleValue() < -1 || v.doubleValue() > 1 ? ExprNullValue.of() : new ExprDoubleValue(Math.acos(v.doubleValue()))), DOUBLE, type)).collect(Collectors.toList())); @@ -557,9 +537,9 @@ private static DefaultFunctionResolver acos() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver asin() { - return FunctionDSL.define(BuiltinFunctionName.ASIN.getName(), + return define(BuiltinFunctionName.ASIN.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> v.doubleValue() < -1 || v.doubleValue() > 1 ? ExprNullValue.of() : new ExprDoubleValue(Math.asin(v.doubleValue()))), DOUBLE, type)).collect(Collectors.toList())); @@ -578,15 +558,14 @@ private static DefaultFunctionResolver atan() { FunctionBuilder>>> builder = new ImmutableList.Builder<>(); for (ExprType type : ExprCoreType.numberTypes()) { - builder.add(FunctionDSL.impl(FunctionDSL - .nullMissingHandling(x -> new ExprDoubleValue(Math.atan(x.doubleValue()))), type, - DOUBLE)); - builder.add(FunctionDSL.impl(FunctionDSL - .nullMissingHandling((y, x) -> new ExprDoubleValue(Math.atan2(y.doubleValue(), - x.doubleValue()))), DOUBLE, type, type)); + builder.add(impl(nullMissingHandling(x -> new ExprDoubleValue(Math.atan(x.doubleValue()))), + type, DOUBLE)); + builder.add(impl(nullMissingHandling((y, x) -> new ExprDoubleValue(Math.atan2(y.doubleValue(), + x.doubleValue()))), + DOUBLE, type, type)); } - return FunctionDSL.define(BuiltinFunctionName.ATAN.getName(), builder.build()); + return define(BuiltinFunctionName.ATAN.getName(), builder.build()); } /** @@ -601,12 +580,11 @@ private static DefaultFunctionResolver atan2() { FunctionBuilder>>> builder = new ImmutableList.Builder<>(); for (ExprType type : ExprCoreType.numberTypes()) { - builder.add(FunctionDSL.impl(FunctionDSL - .nullMissingHandling((y, x) -> new ExprDoubleValue(Math.atan2(y.doubleValue(), + builder.add(impl(nullMissingHandling((y, x) -> new ExprDoubleValue(Math.atan2(y.doubleValue(), x.doubleValue()))), DOUBLE, type, type)); } - return FunctionDSL.define(BuiltinFunctionName.ATAN2.getName(), builder.build()); + return define(BuiltinFunctionName.ATAN2.getName(), builder.build()); } /** @@ -638,9 +616,9 @@ private static DefaultFunctionResolver cosh() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver cot() { - return FunctionDSL.define(BuiltinFunctionName.COT.getName(), + return define(BuiltinFunctionName.COT.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> { Double value = v.doubleValue(); if (value == 0) { diff --git a/core/src/main/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperator.java b/core/src/main/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperator.java index 99399249c2..cc5b47bde1 100644 --- a/core/src/main/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperator.java +++ b/core/src/main/java/org/opensearch/sql/expression/operator/predicate/BinaryPredicateOperator.java @@ -13,6 +13,9 @@ import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN; import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; import static org.opensearch.sql.data.type.ExprCoreType.STRING; +import static org.opensearch.sql.expression.function.FunctionDSL.define; +import static org.opensearch.sql.expression.function.FunctionDSL.impl; +import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandling; import com.google.common.collect.ImmutableTable; import com.google.common.collect.Table; @@ -24,7 +27,6 @@ import org.opensearch.sql.expression.function.BuiltinFunctionName; import org.opensearch.sql.expression.function.BuiltinFunctionRepository; import org.opensearch.sql.expression.function.DefaultFunctionResolver; -import org.opensearch.sql.expression.function.FunctionDSL; import org.opensearch.sql.utils.OperatorUtils; /** @@ -141,116 +143,83 @@ public static void register(BuiltinFunctionRepository repository) { .build(); private static DefaultFunctionResolver and() { - return FunctionDSL.define(BuiltinFunctionName.AND.getName(), FunctionDSL - .impl((v1, v2) -> lookupTableFunction(v1, v2, andTable), BOOLEAN, BOOLEAN, - BOOLEAN)); + return define(BuiltinFunctionName.AND.getName(), + impl((v1, v2) -> lookupTableFunction(v1, v2, andTable), BOOLEAN, BOOLEAN, BOOLEAN)); } private static DefaultFunctionResolver or() { - return FunctionDSL.define(BuiltinFunctionName.OR.getName(), FunctionDSL - .impl((v1, v2) -> lookupTableFunction(v1, v2, orTable), BOOLEAN, BOOLEAN, - BOOLEAN)); + return define(BuiltinFunctionName.OR.getName(), + impl((v1, v2) -> lookupTableFunction(v1, v2, orTable), BOOLEAN, BOOLEAN, BOOLEAN)); } private static DefaultFunctionResolver xor() { - return FunctionDSL.define(BuiltinFunctionName.XOR.getName(), FunctionDSL - .impl((v1, v2) -> lookupTableFunction(v1, v2, xorTable), BOOLEAN, BOOLEAN, - BOOLEAN)); + return define(BuiltinFunctionName.XOR.getName(), + impl((v1, v2) -> lookupTableFunction(v1, v2, xorTable), BOOLEAN, BOOLEAN, BOOLEAN)); } private static DefaultFunctionResolver equal() { - return FunctionDSL.define(BuiltinFunctionName.EQUAL.getName(), - ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL.impl( - FunctionDSL.nullMissingHandling((v1, v2) -> ExprBooleanValue.of(v1.equals(v2))), - BOOLEAN, type, type)) - .collect( - Collectors.toList())); + return define(BuiltinFunctionName.EQUAL.getName(), ExprCoreType.coreTypes().stream() + .map(type -> impl(nullMissingHandling( + (v1, v2) -> ExprBooleanValue.of(v1.equals(v2))), + BOOLEAN, type, type)) + .collect(Collectors.toList())); } private static DefaultFunctionResolver notEqual() { - return FunctionDSL - .define(BuiltinFunctionName.NOTEQUAL.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl( - FunctionDSL - .nullMissingHandling((v1, v2) -> ExprBooleanValue.of(!v1.equals(v2))), - BOOLEAN, - type, - type)) - .collect( - Collectors.toList())); + return define(BuiltinFunctionName.NOTEQUAL.getName(), ExprCoreType.coreTypes().stream() + .map(type -> impl(nullMissingHandling( + (v1, v2) -> ExprBooleanValue.of(!v1.equals(v2))), + BOOLEAN, type, type)) + .collect(Collectors.toList())); } private static DefaultFunctionResolver less() { - return FunctionDSL - .define(BuiltinFunctionName.LESS.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl(FunctionDSL - .nullMissingHandling((v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) < 0)), - BOOLEAN, - type, type)) - .collect( - Collectors.toList())); + return define(BuiltinFunctionName.LESS.getName(), ExprCoreType.coreTypes().stream() + .map(type -> impl(nullMissingHandling( + (v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) < 0)), + BOOLEAN,type, type)) + .collect(Collectors.toList())); } private static DefaultFunctionResolver lte() { - return FunctionDSL - .define(BuiltinFunctionName.LTE.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl( - FunctionDSL - .nullMissingHandling( - (v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) <= 0)), - BOOLEAN, - type, type)) - .collect( - Collectors.toList())); + return define(BuiltinFunctionName.LTE.getName(), ExprCoreType.coreTypes().stream() + .map(type -> impl(nullMissingHandling( + (v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) <= 0)), + BOOLEAN, type, type)) + .collect(Collectors.toList())); } private static DefaultFunctionResolver greater() { - return FunctionDSL - .define(BuiltinFunctionName.GREATER.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl(FunctionDSL - .nullMissingHandling((v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) > 0)), - BOOLEAN, type, type)) - .collect( - Collectors.toList())); + return define(BuiltinFunctionName.GREATER.getName(), ExprCoreType.coreTypes().stream() + .map(type -> impl(nullMissingHandling( + (v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) > 0)), + BOOLEAN, type, type)) + .collect(Collectors.toList())); } private static DefaultFunctionResolver gte() { - return FunctionDSL - .define(BuiltinFunctionName.GTE.getName(), ExprCoreType.coreTypes().stream() - .map(type -> FunctionDSL - .impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) >= 0)), - BOOLEAN, - type, type)) - .collect( - Collectors.toList())); + return define(BuiltinFunctionName.GTE.getName(), ExprCoreType.coreTypes().stream() + .map(type -> impl(nullMissingHandling( + (v1, v2) -> ExprBooleanValue.of(v1.compareTo(v2) >= 0)), + BOOLEAN, type, type)) + .collect(Collectors.toList())); } private static DefaultFunctionResolver like() { - return FunctionDSL.define(BuiltinFunctionName.LIKE.getName(), FunctionDSL - .impl(FunctionDSL.nullMissingHandling(OperatorUtils::matches), BOOLEAN, STRING, - STRING)); + return define(BuiltinFunctionName.LIKE.getName(), + impl(nullMissingHandling(OperatorUtils::matches), BOOLEAN, STRING, STRING)); } private static DefaultFunctionResolver regexp() { - return FunctionDSL.define(BuiltinFunctionName.REGEXP.getName(), FunctionDSL - .impl(FunctionDSL.nullMissingHandling(OperatorUtils::matchesRegexp), - INTEGER, STRING, STRING)); + return define(BuiltinFunctionName.REGEXP.getName(), + impl(nullMissingHandling(OperatorUtils::matchesRegexp), INTEGER, STRING, STRING)); } private static DefaultFunctionResolver notLike() { - return FunctionDSL.define(BuiltinFunctionName.NOT_LIKE.getName(), FunctionDSL - .impl(FunctionDSL.nullMissingHandling( + return define(BuiltinFunctionName.NOT_LIKE.getName(), + impl(nullMissingHandling( (v1, v2) -> UnaryPredicateOperator.not(OperatorUtils.matches(v1, v2))), - BOOLEAN, - STRING, - STRING)); + BOOLEAN, STRING, STRING)); } private static ExprValue lookupTableFunction(ExprValue arg1, ExprValue arg2, diff --git a/core/src/main/java/org/opensearch/sql/expression/parse/ParseExpression.java b/core/src/main/java/org/opensearch/sql/expression/parse/ParseExpression.java index d99242bdde..8d1ebcce08 100644 --- a/core/src/main/java/org/opensearch/sql/expression/parse/ParseExpression.java +++ b/core/src/main/java/org/opensearch/sql/expression/parse/ParseExpression.java @@ -24,7 +24,7 @@ /** * ParseExpression. */ -@EqualsAndHashCode +@EqualsAndHashCode(callSuper = false) @ToString public abstract class ParseExpression extends FunctionExpression { @Getter diff --git a/core/src/main/java/org/opensearch/sql/planner/physical/collector/Rounding.java b/core/src/main/java/org/opensearch/sql/planner/physical/collector/Rounding.java index 71ae5dc7c3..782c931046 100644 --- a/core/src/main/java/org/opensearch/sql/planner/physical/collector/Rounding.java +++ b/core/src/main/java/org/opensearch/sql/planner/physical/collector/Rounding.java @@ -11,12 +11,12 @@ import static org.opensearch.sql.data.type.ExprCoreType.LONG; import static org.opensearch.sql.data.type.ExprCoreType.TIME; import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneId; import java.time.temporal.ChronoField; import java.util.Arrays; import java.util.concurrent.TimeUnit; @@ -101,8 +101,8 @@ public DatetimeRounding(ExprValue interval, String unit) { @Override public ExprValue round(ExprValue var) { Instant instant = Instant.ofEpochMilli(dateTimeUnit.round(var.datetimeValue() - .atZone(ZoneId.of("UTC")).toInstant().toEpochMilli(), interval.integerValue())); - return new ExprDatetimeValue(instant.atZone(ZoneId.of("UTC")).toLocalDateTime()); + .atZone(UTC_ZONE_ID).toInstant().toEpochMilli(), interval.integerValue())); + return new ExprDatetimeValue(instant.atZone(UTC_ZONE_ID).toLocalDateTime()); } } @@ -119,8 +119,8 @@ public DateRounding(ExprValue interval, String unit) { @Override public ExprValue round(ExprValue var) { Instant instant = Instant.ofEpochMilli(dateTimeUnit.round(var.dateValue().atStartOfDay() - .atZone(ZoneId.of("UTC")).toInstant().toEpochMilli(), interval.integerValue())); - return new ExprDateValue(instant.atZone(ZoneId.of("UTC")).toLocalDate()); + .atZone(UTC_ZONE_ID).toInstant().toEpochMilli(), interval.integerValue())); + return new ExprDateValue(instant.atZone(UTC_ZONE_ID).toLocalDate()); } } @@ -142,7 +142,7 @@ public ExprValue round(ExprValue var) { Instant instant = Instant.ofEpochMilli(dateTimeUnit.round(var.timeValue().getLong( ChronoField.MILLI_OF_DAY), interval.integerValue())); - return new ExprTimeValue(instant.atZone(ZoneId.of("UTC")).toLocalTime()); + return new ExprTimeValue(instant.atZone(UTC_ZONE_ID).toLocalTime()); } } diff --git a/core/src/main/java/org/opensearch/sql/utils/DateTimeFormatters.java b/core/src/main/java/org/opensearch/sql/utils/DateTimeFormatters.java index a9ea53f142..39726bc975 100644 --- a/core/src/main/java/org/opensearch/sql/utils/DateTimeFormatters.java +++ b/core/src/main/java/org/opensearch/sql/utils/DateTimeFormatters.java @@ -44,6 +44,9 @@ public class DateTimeFormatters { //Length of a date formatted as MDD. public static final int SINGLE_DIGIT_MONTH_DATE_LENGTH = 3; + private static final int MIN_FRACTION_SECONDS = 0; + private static final int MAX_FRACTION_SECONDS = 9; + public static final DateTimeFormatter TIME_ZONE_FORMATTER_NO_COLON = new DateTimeFormatterBuilder() .appendOffset("+HHmm", "Z") @@ -123,9 +126,6 @@ public class DateTimeFormatters { public static final DateTimeFormatter DATE_TIME_FORMATTER_WITHOUT_NANO = SQL_LITERAL_DATE_TIME_FORMAT; - private static final int MIN_FRACTION_SECONDS = 0; - private static final int MAX_FRACTION_SECONDS = 9; - public static final DateTimeFormatter DATE_TIME_FORMATTER_VARIABLE_NANOS = new DateTimeFormatterBuilder() .appendPattern("uuuu-MM-dd HH:mm:ss") @@ -204,9 +204,21 @@ public class DateTimeFormatters { .toFormatter() .withResolverStyle(ResolverStyle.STRICT); + // uuuu-MM-dd HH:mm:ss[xxx] public static final DateTimeFormatter DATE_TIME_FORMATTER_STRICT_WITH_TZ = new DateTimeFormatterBuilder() .appendPattern("uuuu-MM-dd HH:mm:ss[xxx]") .toFormatter() .withResolverStyle(ResolverStyle.STRICT); + + // uuuu-MM-dd HH:mm:ss[xxx] + public static final DateTimeFormatter DATE_TIME_FORMATTER_WITH_TZ = + new DateTimeFormatterBuilder() + .appendPattern("uuuu-MM-dd HH:mm:ss[xxx]") + .appendFraction( + ChronoField.NANO_OF_SECOND, + MIN_FRACTION_SECONDS, + MAX_FRACTION_SECONDS, + true) + .toFormatter(); } diff --git a/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java b/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java index 06d40ea6aa..74fdf42571 100644 --- a/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java +++ b/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java @@ -48,8 +48,8 @@ public static long roundWeek(long utcMillis, int interval) { * @return Rounded date/time value in utc millis */ public static long roundMonth(long utcMillis, int interval) { - ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")); - ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(ZoneId.of("UTC")) + ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, UTC_ZONE_ID); + ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(UTC_ZONE_ID) .plusMonths(interval); long monthDiff = (zonedDateTime.getYear() - initDateTime.getYear()) * 12L + zonedDateTime .getMonthValue() - initDateTime.getMonthValue(); @@ -65,8 +65,8 @@ public static long roundMonth(long utcMillis, int interval) { * @return Rounded date/time value in utc millis */ public static long roundQuarter(long utcMillis, int interval) { - ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")); - ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(ZoneId.of("UTC")) + ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, UTC_ZONE_ID); + ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(UTC_ZONE_ID) .plusMonths(interval * 3L); long monthDiff = ((zonedDateTime.getYear() - initDateTime.getYear()) * 12L + zonedDateTime .getMonthValue() - initDateTime.getMonthValue()); @@ -82,8 +82,8 @@ public static long roundQuarter(long utcMillis, int interval) { * @return Rounded date/time value in utc millis */ public static long roundYear(long utcMillis, int interval) { - ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")); - ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(ZoneId.of("UTC")); + ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, UTC_ZONE_ID); + ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(UTC_ZONE_ID); int yearDiff = zonedDateTime.getYear() - initDateTime.getYear(); int yearToAdd = (yearDiff / interval) * interval; return initDateTime.plusYears(yearToAdd).toInstant().toEpochMilli(); @@ -151,4 +151,6 @@ public static LocalDate extractDate(ExprValue value, ? ((ExprTimeValue) value).dateValue(functionProperties) : value.dateValue(); } + + public static final ZoneId UTC_ZONE_ID = ZoneId.of("UTC"); } diff --git a/core/src/test/java/org/opensearch/sql/data/model/DateTimeValueTest.java b/core/src/test/java/org/opensearch/sql/data/model/DateTimeValueTest.java index a335478e19..c78545f9ae 100644 --- a/core/src/test/java/org/opensearch/sql/data/model/DateTimeValueTest.java +++ b/core/src/test/java/org/opensearch/sql/data/model/DateTimeValueTest.java @@ -11,6 +11,7 @@ import static org.opensearch.sql.data.model.ExprValueUtils.integerValue; import static org.opensearch.sql.data.type.ExprCoreType.TIME; import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import java.time.LocalDate; import java.time.LocalDateTime; @@ -47,7 +48,7 @@ public void timeValueInterfaceTest() { assertEquals(today, timeValue.dateValue(functionProperties)); assertEquals(today.atTime(1, 1, 1), timeValue.datetimeValue(functionProperties)); assertEquals(ZonedDateTime.of(LocalTime.parse("01:01:01").atDate(today), - ExprTimestampValue.ZONE).toInstant(), timeValue.timestampValue(functionProperties)); + UTC_ZONE_ID).toInstant(), timeValue.timestampValue(functionProperties)); assertEquals("01:01:01", timeValue.value()); assertEquals("TIME '01:01:01'", timeValue.toString()); @@ -62,7 +63,7 @@ public void timestampValueInterfaceTest() { assertEquals(TIMESTAMP, timestampValue.type()); assertEquals(ZonedDateTime.of(LocalDateTime.parse("2020-07-07T01:01:01"), - ExprTimestampValue.ZONE).toInstant(), timestampValue.timestampValue()); + UTC_ZONE_ID).toInstant(), timestampValue.timestampValue()); assertEquals("2020-07-07 01:01:01", timestampValue.value()); assertEquals("TIMESTAMP '2020-07-07 01:01:01'", timestampValue.toString()); assertEquals(LocalDate.parse("2020-07-07"), timestampValue.dateValue()); @@ -80,7 +81,7 @@ public void dateValueInterfaceTest() { assertEquals(LocalTime.parse("00:00:00"), dateValue.timeValue()); assertEquals(LocalDateTime.parse("2012-07-07T00:00:00"), dateValue.datetimeValue()); assertEquals(ZonedDateTime.of(LocalDateTime.parse("2012-07-07T00:00:00"), - ExprTimestampValue.ZONE).toInstant(), dateValue.timestampValue()); + UTC_ZONE_ID).toInstant(), dateValue.timestampValue()); ExpressionEvaluationException exception = assertThrows(ExpressionEvaluationException.class, () -> integerValue(1).dateValue()); assertEquals("invalid to get dateValue from value of type INTEGER", @@ -95,7 +96,7 @@ public void datetimeValueInterfaceTest() { assertEquals(LocalDate.parse("2020-08-17"), datetimeValue.dateValue()); assertEquals(LocalTime.parse("19:44:00"), datetimeValue.timeValue()); assertEquals(ZonedDateTime.of(LocalDateTime.parse("2020-08-17T19:44:00"), - ExprTimestampValue.ZONE).toInstant(), datetimeValue.timestampValue()); + UTC_ZONE_ID).toInstant(), datetimeValue.timestampValue()); assertEquals("DATETIME '2020-08-17 19:44:00'", datetimeValue.toString()); assertThrows(ExpressionEvaluationException.class, () -> integerValue(1).datetimeValue(), "invalid to get datetimeValue from value of type INTEGER"); diff --git a/core/src/test/java/org/opensearch/sql/data/model/ExprValueUtilsTest.java b/core/src/test/java/org/opensearch/sql/data/model/ExprValueUtilsTest.java index 3c3f5a2c24..c4a00fe5ca 100644 --- a/core/src/test/java/org/opensearch/sql/data/model/ExprValueUtilsTest.java +++ b/core/src/test/java/org/opensearch/sql/data/model/ExprValueUtilsTest.java @@ -20,6 +20,7 @@ import static org.opensearch.sql.data.type.ExprCoreType.STRUCT; import static org.opensearch.sql.data.type.ExprCoreType.TIME; import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -29,7 +30,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.AbstractMap; import java.util.ArrayList; @@ -114,7 +114,7 @@ private static Stream getValueTestArgumentStream() { LocalDate.parse("2012-08-07"), LocalTime.parse("18:00:00"), LocalDateTime.parse("2012-08-07T18:00:00"), - ZonedDateTime.of(LocalDateTime.parse("2012-08-07T18:00:00"), ZoneId.of("UTC")).toInstant(), + ZonedDateTime.of(LocalDateTime.parse("2012-08-07T18:00:00"), UTC_ZONE_ID).toInstant(), Duration.ofSeconds(100) ); Stream.Builder builder = Stream.builder(); diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/ConvertTZTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/ConvertTZTest.java index 38cb3c5a63..7bc788c9a7 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/ConvertTZTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/ConvertTZTest.java @@ -6,31 +6,18 @@ package org.opensearch.sql.expression.datetime; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.opensearch.sql.data.model.ExprValueUtils.nullValue; import static org.opensearch.sql.data.type.ExprCoreType.DATETIME; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import org.opensearch.sql.data.model.ExprDatetimeValue; -import org.opensearch.sql.data.model.ExprValue; import org.opensearch.sql.expression.DSL; -import org.opensearch.sql.expression.Expression; import org.opensearch.sql.expression.ExpressionTestBase; import org.opensearch.sql.expression.FunctionExpression; -import org.opensearch.sql.expression.env.Environment; - - -@ExtendWith(MockitoExtension.class) class ConvertTZTest extends ExpressionTestBase { - @Mock - Environment env; - @Test public void invalidDate() { FunctionExpression expr = DSL.convert_tz(DSL.datetime( @@ -38,7 +25,7 @@ public void invalidDate() { DSL.literal("+00:00"), DSL.literal("+00:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -48,7 +35,7 @@ public void conversionFromNoOffset() { DSL.literal("+00:00"), DSL.literal("+10:00")); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2008-05-16 08:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2008-05-16 08:00:00"), expr.valueOf()); } @Test @@ -58,7 +45,7 @@ public void conversionToInvalidInput3Over() { DSL.literal("+00:00"), DSL.literal("+16:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -68,7 +55,7 @@ public void conversionToInvalidInput3Under() { DSL.literal("+00:00"), DSL.literal("-16:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -78,7 +65,7 @@ public void conversionFromPositiveToPositive() { DSL.literal("+15:00"), DSL.literal("+01:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -88,7 +75,7 @@ public void invalidInput2Under() { DSL.literal("-15:00"), DSL.literal("+01:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -98,7 +85,7 @@ public void invalidInput3Over() { DSL.literal("-12:00"), DSL.literal("+15:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -108,7 +95,7 @@ public void conversionToPositiveEdge() { DSL.literal("+00:00"), DSL.literal("+14:00")); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2008-05-16 12:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2008-05-16 12:00:00"), expr.valueOf()); } @Test @@ -118,7 +105,7 @@ public void conversionToNegativeEdge() { DSL.literal("+00:01"), DSL.literal("-13:59")); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2008-05-15 08:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2008-05-15 08:00:00"), expr.valueOf()); } @Test @@ -128,7 +115,7 @@ public void invalidInput2() { DSL.literal("+)()"), DSL.literal("+12:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -138,7 +125,7 @@ public void invalidInput3() { DSL.literal("+00:00"), DSL.literal("test")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -148,7 +135,7 @@ public void invalidInput1() { DSL.literal("+00:00"), DSL.literal("+00:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -158,7 +145,7 @@ public void invalidDateFeb30() { DSL.literal("+00:00"), DSL.literal("+00:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -168,7 +155,7 @@ public void invalidDateApril31() { DSL.literal("+00:00"), DSL.literal("+00:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -178,6 +165,6 @@ public void invalidMonth13() { DSL.literal("+00:00"), DSL.literal("+00:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } } diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java index 4cbe515cde..2f650eeda3 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java @@ -10,15 +10,11 @@ import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.when; import static org.opensearch.sql.data.model.ExprValueUtils.integerValue; import static org.opensearch.sql.data.model.ExprValueUtils.longValue; -import static org.opensearch.sql.data.model.ExprValueUtils.missingValue; import static org.opensearch.sql.data.model.ExprValueUtils.nullValue; import static org.opensearch.sql.data.model.ExprValueUtils.stringValue; import static org.opensearch.sql.data.type.ExprCoreType.DATE; -import static org.opensearch.sql.data.type.ExprCoreType.DATETIME; import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; import static org.opensearch.sql.data.type.ExprCoreType.LONG; import static org.opensearch.sql.data.type.ExprCoreType.STRING; @@ -32,14 +28,10 @@ import java.util.List; import java.util.stream.Stream; import lombok.AllArgsConstructor; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import org.opensearch.sql.data.model.ExprDateValue; import org.opensearch.sql.data.model.ExprDatetimeValue; import org.opensearch.sql.data.model.ExprDoubleValue; @@ -50,34 +42,15 @@ import org.opensearch.sql.data.model.ExprTimeValue; import org.opensearch.sql.data.model.ExprTimestampValue; import org.opensearch.sql.data.model.ExprValue; -import org.opensearch.sql.data.type.ExprCoreType; import org.opensearch.sql.exception.SemanticCheckException; import org.opensearch.sql.expression.DSL; import org.opensearch.sql.expression.Expression; import org.opensearch.sql.expression.ExpressionTestBase; import org.opensearch.sql.expression.FunctionExpression; import org.opensearch.sql.expression.LiteralExpression; -import org.opensearch.sql.expression.env.Environment; -import org.opensearch.sql.expression.function.FunctionProperties; -@ExtendWith(MockitoExtension.class) class DateTimeFunctionTest extends ExpressionTestBase { - @Mock - Environment env; - - @Mock - Expression nullRef; - - @Mock - Expression missingRef; - - @BeforeEach - public void setup() { - when(nullRef.valueOf(env)).thenReturn(nullValue()); - when(missingRef.valueOf(env)).thenReturn(missingValue()); - } - final List dateFormatTesters = ImmutableList.of( new DateFormatTester("1998-01-31 13:14:15.012345", ImmutableList.of("%H","%I","%k","%l","%i","%p","%r","%S","%T"," %M", @@ -174,11 +147,6 @@ FunctionExpression getDateFormatExpression() { @Test public void date() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.date(nullRef))); - assertEquals(missingValue(), eval(DSL.date(missingRef))); - FunctionExpression expr = DSL.date(DSL.literal("2020-08-17")); assertEquals(DATE, expr.type()); assertEquals(new ExprDateValue("2020-08-17"), eval(expr)); @@ -198,17 +166,10 @@ public void date() { assertEquals(DATE, expr.type()); assertEquals(new ExprDateValue("2020-08-17 12:12"), eval(expr)); assertEquals("date(DATE '2020-08-17')", expr.toString()); - - } @Test public void day() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.day(nullRef))); - assertEquals(missingValue(), eval(DSL.day(missingRef))); - FunctionExpression expression = DSL.day(DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(INTEGER, expression.type()); assertEquals("day(DATE '2020-08-07')", expression.toString()); @@ -222,11 +183,6 @@ public void day() { @Test public void dayName() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.dayname(nullRef))); - assertEquals(missingValue(), eval(DSL.dayname(missingRef))); - FunctionExpression expression = DSL.dayname(DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(STRING, expression.type()); assertEquals("dayname(DATE '2020-08-07')", expression.toString()); @@ -240,11 +196,6 @@ public void dayName() { @Test public void dayOfMonth() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.dayofmonth(functionProperties, nullRef))); - assertEquals(missingValue(), eval(DSL.dayofmonth(functionProperties, missingRef))); - FunctionExpression expression = DSL.dayofmonth( functionProperties, DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(INTEGER, expression.type()); @@ -264,10 +215,6 @@ private void testDayOfMonthWithUnderscores(FunctionExpression dateExpression, in @Test public void dayOfMonthWithUnderscores() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - - FunctionExpression expression1 = DSL.dayofmonth( functionProperties, DSL.literal(new ExprDateValue("2020-08-07"))); FunctionExpression expression2 = DSL.dayofmonth(functionProperties, DSL.literal("2020-07-08")); @@ -278,14 +225,11 @@ public void dayOfMonthWithUnderscores() { () -> testDayOfMonthWithUnderscores(expression2, 8), () -> assertEquals("dayofmonth(\"2020-07-08\")", expression2.toString()) - ); } @Test public void testDayOfMonthWithTimeType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expression = DSL.day_of_month( functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))); @@ -304,9 +248,6 @@ private void testInvalidDayOfMonth(String date) { @Test public void dayOfMonthWithUnderscoresLeapYear() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - //Feb. 29 of a leap year testDayOfMonthWithUnderscores(DSL.day_of_month( functionProperties, DSL.literal("2020-02-29")), 29); @@ -317,14 +258,7 @@ public void dayOfMonthWithUnderscoresLeapYear() { @Test public void dayOfMonthWithUnderscoresInvalidArguments() { - lenient().when(nullRef.type()).thenReturn(DATE); - lenient().when(missingRef.type()).thenReturn(DATE); - assertAll( - () -> assertEquals(nullValue(), eval(DSL.day_of_month(functionProperties, nullRef))), - () -> assertEquals( - missingValue(), eval(DSL.day_of_month(functionProperties, missingRef))), - //40th day of the month () -> assertThrows( SemanticCheckException.class, () -> testInvalidDayOfMonth("2021-02-40")), @@ -348,9 +282,6 @@ private void dayOfWeekQuery( @Test public void dayOfWeek() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression1 = DSL.dayofweek( functionProperties, DSL.literal(new ExprDateValue("2020-08-07"))); @@ -386,9 +317,6 @@ private void dayOfWeekWithUnderscoresQuery( @Test public void dayOfWeekWithUnderscores() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression1 = DSL.day_of_week( functionProperties, DSL.literal(new ExprDateValue("2020-08-07"))); @@ -416,8 +344,6 @@ public void dayOfWeekWithUnderscores() { @Test public void testDayOfWeekWithTimeType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expression = DSL.day_of_week( functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))); @@ -439,9 +365,6 @@ private void testInvalidDayOfWeek(String date) { @Test public void dayOfWeekWithUnderscoresLeapYear() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - assertAll( //Feb. 29 of a leap year () -> dayOfWeekWithUnderscoresQuery(DSL.day_of_week( @@ -463,11 +386,6 @@ public void dayOfWeekWithUnderscoresLeapYear() { @Test public void dayOfWeekWithUnderscoresInvalidArgument() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.day_of_week(functionProperties, nullRef))); - assertEquals(missingValue(), eval(DSL.day_of_week(functionProperties, missingRef))); - assertAll( //40th day of the month () -> assertThrows(SemanticCheckException.class, @@ -485,11 +403,6 @@ public void dayOfWeekWithUnderscoresInvalidArgument() { @Test public void dayOfYear() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.dayofyear(nullRef))); - assertEquals(missingValue(), eval(DSL.dayofyear(missingRef))); - FunctionExpression expression = DSL.dayofyear(DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(INTEGER, expression.type()); assertEquals("dayofyear(DATE '2020-08-07')", expression.toString()); @@ -537,9 +450,6 @@ public void dayOfYearWithUnderscores( LiteralExpression arg, String expectedString, int expectedResult) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - validateStringFormat( DSL.day_of_year(functionProperties, arg), expectedString, @@ -549,9 +459,6 @@ public void dayOfYearWithUnderscores( @Test public void testDayOfYearWithTimeType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - validateStringFormat( DSL.day_of_year(functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))), "day_of_year(TIME '12:23:34')", @@ -570,9 +477,6 @@ public void dayOfYearWithUnderscoresQuery(String date, int dayOfYear) { @Test public void dayOfYearWithUnderscoresDifferentArgumentFormats() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression1 = DSL.day_of_year( functionProperties, DSL.literal(new ExprDateValue("2020-08-07"))); @@ -597,9 +501,6 @@ public void dayOfYearWithUnderscoresDifferentArgumentFormats() { @Test public void dayOfYearWithUnderscoresCornerCaseDates() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - assertAll( //31st of December during non leap year (should be 365) () -> dayOfYearWithUnderscoresQuery("2019-12-31", 365), @@ -612,9 +513,6 @@ public void dayOfYearWithUnderscoresCornerCaseDates() { @Test public void dayOfYearWithUnderscoresLeapYear() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - assertAll( //28th of Feb () -> dayOfYearWithUnderscoresQuery("2020-02-28", 59), @@ -644,13 +542,7 @@ private void invalidDayOfYearQuery(String date) { @Test public void invalidDayOfYearArgument() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertAll( - () -> assertEquals(nullValue(), eval(DSL.day_of_year(functionProperties, nullRef))), - () -> assertEquals(missingValue(), eval(DSL.day_of_year(functionProperties, missingRef))), - //29th of Feb non-leapyear () -> assertThrows( SemanticCheckException.class, @@ -670,15 +562,10 @@ public void invalidDayOfYearArgument() { @Test public void from_days() { - when(nullRef.type()).thenReturn(LONG); - when(missingRef.type()).thenReturn(LONG); - assertEquals(nullValue(), eval(DSL.from_days(nullRef))); - assertEquals(missingValue(), eval(DSL.from_days(missingRef))); - FunctionExpression expression = DSL.from_days(DSL.literal(new ExprLongValue(730669))); assertEquals(DATE, expression.type()); assertEquals("from_days(730669)", expression.toString()); - assertEquals(new ExprDateValue("2000-07-03"), expression.valueOf(env)); + assertEquals(new ExprDateValue("2000-07-03"), expression.valueOf()); } private static Stream getTestDataForGetFormat() { @@ -719,9 +606,6 @@ private void getFormatQuery(LiteralExpression argType, public void testGetFormat(String arg, String format, String expectedResult) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - getFormatQuery( DSL.literal(arg), DSL.literal(new ExprStringValue(format)), @@ -730,8 +614,6 @@ public void testGetFormat(String arg, @Test public void testGetFormatInvalidFormat() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expr = DSL.get_format( DSL.literal("DATE"), DSL.literal("1SA")); @@ -740,11 +622,6 @@ public void testGetFormatInvalidFormat() { @Test public void hour() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertEquals(nullValue(), eval(DSL.hour(nullRef))); - assertEquals(missingValue(), eval(DSL.hour(missingRef))); - FunctionExpression expression = DSL.hour(DSL.literal(new ExprTimeValue("01:02:03"))); assertEquals(INTEGER, expression.type()); assertEquals(integerValue(1), eval(expression)); @@ -757,17 +634,17 @@ public void hour() { expression = DSL.hour(DSL.literal(new ExprTimestampValue("2020-08-17 01:02:03"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(1), expression.valueOf(env)); + assertEquals(integerValue(1), expression.valueOf()); assertEquals("hour(TIMESTAMP '2020-08-17 01:02:03')", expression.toString()); expression = DSL.hour(DSL.literal(new ExprDatetimeValue("2020-08-17 01:02:03"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(1), expression.valueOf(env)); + assertEquals(integerValue(1), expression.valueOf()); assertEquals("hour(DATETIME '2020-08-17 01:02:03')", expression.toString()); expression = DSL.hour(DSL.literal("2020-08-17 01:02:03")); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(1), expression.valueOf(env)); + assertEquals(integerValue(1), expression.valueOf()); assertEquals("hour(\"2020-08-17 01:02:03\")", expression.toString()); } @@ -778,9 +655,6 @@ private void testInvalidMinuteOfDay(String date) { @Test public void invalidMinuteOfDay() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - assertThrows(SemanticCheckException.class, () -> testInvalidMinuteOfDay("2022-12-14 12:23:3400")); assertThrows(SemanticCheckException.class, @@ -809,9 +683,6 @@ private void hourOfDayQuery(FunctionExpression dateExpression, int hour) { @Test public void hourOfDay() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression1 = DSL.hour_of_day(DSL.literal(new ExprTimeValue("01:02:03"))); FunctionExpression expression2 = DSL.hour_of_day(DSL.literal("01:02:03")); FunctionExpression expression3 = DSL.hour_of_day( @@ -845,12 +716,7 @@ private void invalidHourOfDayQuery(String time) { @Test public void hourOfDayInvalidArguments() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertAll( - () -> assertEquals(nullValue(), eval(DSL.hour(nullRef))), - () -> assertEquals(missingValue(), eval(DSL.hour(missingRef))), //Invalid Seconds () -> assertThrows(SemanticCheckException.class, () -> invalidHourOfDayQuery("12:23:61")), //Invalid Minutes @@ -897,9 +763,6 @@ private static Stream getTestDataForLastDay() { @ParameterizedTest(name = "{2}") @MethodSource("getTestDataForLastDay") public void testLastDay(ExprValue testedDateTime, String expectedResult, String expectedQuery) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - checkForExpectedDay( DSL.last_day(functionProperties, DSL.literal(testedDateTime)), expectedResult, @@ -909,9 +772,6 @@ public void testLastDay(ExprValue testedDateTime, String expectedResult, String @Test public void testLastDayWithTimeType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression = DSL.last_day( functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))); @@ -933,19 +793,11 @@ private void lastDay(String date) { @Test public void testLastDayInvalidArgument() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - assertThrows(SemanticCheckException.class, () -> lastDay("asdfasdf")); } @Test public void microsecond() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertEquals(nullValue(), eval(DSL.microsecond(nullRef))); - assertEquals(missingValue(), eval(DSL.microsecond(missingRef))); - FunctionExpression expression = DSL .microsecond(DSL.literal(new ExprTimeValue("01:02:03.123456"))); assertEquals(INTEGER, expression.type()); @@ -964,32 +816,27 @@ public void microsecond() { expression = DSL.microsecond(DSL.literal(new ExprDatetimeValue("2020-08-17 01:02:03.000010"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(10), expression.valueOf(env)); + assertEquals(integerValue(10), expression.valueOf()); assertEquals("microsecond(DATETIME '2020-08-17 01:02:03.00001')", expression.toString()); expression = DSL.microsecond(DSL.literal(new ExprDatetimeValue("2020-08-17 01:02:03.123456"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(123456), expression.valueOf(env)); + assertEquals(integerValue(123456), expression.valueOf()); assertEquals("microsecond(DATETIME '2020-08-17 01:02:03.123456')", expression.toString()); expression = DSL.microsecond(DSL.literal("2020-08-17 01:02:03.123456")); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(123456), expression.valueOf(env)); + assertEquals(integerValue(123456), expression.valueOf()); assertEquals("microsecond(\"2020-08-17 01:02:03.123456\")", expression.toString()); expression = DSL.microsecond(DSL.literal(new ExprTimestampValue("2020-08-17 01:02:03.000010"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(10), expression.valueOf(env)); + assertEquals(integerValue(10), expression.valueOf()); assertEquals("microsecond(TIMESTAMP '2020-08-17 01:02:03.00001')", expression.toString()); } @Test public void minute() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertEquals(nullValue(), eval(DSL.minute(nullRef))); - assertEquals(missingValue(), eval(DSL.minute(missingRef))); - FunctionExpression expression = DSL.minute(DSL.literal(new ExprTimeValue("01:02:03"))); assertEquals(INTEGER, expression.type()); assertEquals(integerValue(2), eval(expression)); @@ -1002,17 +849,17 @@ public void minute() { expression = DSL.minute(DSL.literal(new ExprTimestampValue("2020-08-17 01:02:03"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(2), expression.valueOf(env)); + assertEquals(integerValue(2), expression.valueOf()); assertEquals("minute(TIMESTAMP '2020-08-17 01:02:03')", expression.toString()); expression = DSL.minute(DSL.literal(new ExprDatetimeValue("2020-08-17 01:02:03"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(2), expression.valueOf(env)); + assertEquals(integerValue(2), expression.valueOf()); assertEquals("minute(DATETIME '2020-08-17 01:02:03')", expression.toString()); expression = DSL.minute(DSL.literal("2020-08-17 01:02:03")); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(2), expression.valueOf(env)); + assertEquals(integerValue(2), expression.valueOf()); assertEquals("minute(\"2020-08-17 01:02:03\")", expression.toString()); } @@ -1024,11 +871,6 @@ private void testMinuteOfDay(String date, int value) { @Test public void minuteOfDay() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertEquals(nullValue(), eval(DSL.minute_of_day(nullRef))); - assertEquals(missingValue(), eval(DSL.minute_of_day(missingRef))); - FunctionExpression expression = DSL.minute_of_day(DSL.literal(new ExprTimeValue("01:02:03"))); assertEquals(INTEGER, expression.type()); assertEquals(integerValue(62), eval(expression)); @@ -1041,17 +883,17 @@ public void minuteOfDay() { expression = DSL.minute_of_day(DSL.literal(new ExprTimestampValue("2020-08-17 01:02:03"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(62), expression.valueOf(env)); + assertEquals(integerValue(62), expression.valueOf()); assertEquals("minute_of_day(TIMESTAMP '2020-08-17 01:02:03')", expression.toString()); expression = DSL.minute_of_day(DSL.literal(new ExprDatetimeValue("2020-08-17 01:02:03"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(62), expression.valueOf(env)); + assertEquals(integerValue(62), expression.valueOf()); assertEquals("minute_of_day(DATETIME '2020-08-17 01:02:03')", expression.toString()); expression = DSL.minute_of_day(DSL.literal("2020-08-17 01:02:03")); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(62), expression.valueOf(env)); + assertEquals(integerValue(62), expression.valueOf()); assertEquals("minute_of_day(\"2020-08-17 01:02:03\")", expression.toString()); testMinuteOfDay("2020-08-17 23:59:59", 1439); @@ -1094,9 +936,6 @@ private static Stream getTestDataForMinuteOfHour() { @ParameterizedTest(name = "{2}") @MethodSource("getTestDataForMinuteOfHour") public void minuteOfHour(LiteralExpression arg, int expectedResult, String expectedString) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - minuteOfHourQuery(DSL.minute_of_hour(arg), expectedResult, expectedString); } @@ -1107,13 +946,7 @@ private void invalidMinuteOfHourQuery(String time) { @Test public void minuteOfHourInvalidArguments() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertAll( - () -> assertEquals(nullValue(), eval(DSL.minute_of_hour(nullRef))), - () -> assertEquals(missingValue(), eval(DSL.minute_of_hour(missingRef))), - //Invalid Seconds () -> assertThrows( SemanticCheckException.class, @@ -1139,11 +972,6 @@ public void minuteOfHourInvalidArguments() { @Test public void month() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.month(nullRef))); - assertEquals(missingValue(), eval(DSL.month(missingRef))); - FunctionExpression expression = DSL.month(DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(INTEGER, expression.type()); assertEquals("month(DATE '2020-08-07')", expression.toString()); @@ -1188,9 +1016,6 @@ private static Stream getTestDataForMonthOfYear() { @ParameterizedTest(name = "{0}") @MethodSource("getTestDataForMonthOfYear") public void monthOfYear(LiteralExpression arg, String expectedString, int expectedResult) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - validateStringFormat( DSL.month_of_year(functionProperties, arg), expectedString, @@ -1200,9 +1025,6 @@ public void monthOfYear(LiteralExpression arg, String expectedString, int expect @Test public void testMonthOfYearWithTimeType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - validateStringFormat( DSL.month_of_year(functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))), "month_of_year(TIME '12:23:34')", @@ -1218,31 +1040,16 @@ private void invalidDatesQuery(String date) throws SemanticCheckException { @Test public void monthOfYearInvalidDates() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertAll( - () -> assertEquals(nullValue(), eval(DSL.month_of_year( - functionProperties, - nullRef))), - () -> assertEquals(missingValue(), eval(DSL.month_of_year( - functionProperties, - missingRef))), () -> assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-01-50")), () -> assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-02-29")), () -> assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-02-31")), () -> assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-13-05")) ); - - - } @Test public void monthOfYearAlternateArgumentSyntaxes() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression = DSL.month_of_year( functionProperties, DSL.literal(new ExprDateValue("2020-08-07"))); @@ -1267,11 +1074,6 @@ public void monthOfYearAlternateArgumentSyntaxes() { @Test public void monthName() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.monthname(nullRef))); - assertEquals(missingValue(), eval(DSL.monthname(missingRef))); - FunctionExpression expression = DSL.monthname(DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(STRING, expression.type()); assertEquals("monthname(DATE '2020-08-07')", expression.toString()); @@ -1290,11 +1092,6 @@ public void monthName() { @Test public void quarter() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.quarter(nullRef))); - assertEquals(missingValue(), eval(DSL.quarter(missingRef))); - FunctionExpression expression = DSL.quarter(DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(INTEGER, expression.type()); assertEquals("quarter(DATE '2020-08-07')", expression.toString()); @@ -1327,8 +1124,6 @@ private static Stream getTestDataForSecToTime() { @ParameterizedTest(name = "{0}") @MethodSource("getTestDataForSecToTime") public void testSecToTime(int seconds, String expected) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expr = DSL.sec_to_time( DSL.literal(new ExprIntegerValue(seconds))); @@ -1349,31 +1144,14 @@ private static Stream getTestDataForSecToTimeWithDecimal() { @ParameterizedTest(name = "{0}") @MethodSource("getTestDataForSecToTimeWithDecimal") public void testSecToTimeWithDecimal(double arg, String expected) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expr = DSL.sec_to_time(DSL.literal(new ExprDoubleValue(arg))); assertEquals(TIME, expr.type()); assertEquals(new ExprTimeValue(expected), eval(expr)); } - @Test - public void testSecToTimeWithNullValue() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expr = DSL.sec_to_time( - DSL.literal(nullValue())); - - assertEquals(nullValue(), eval(expr)); - } - @Test public void second() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertEquals(nullValue(), eval(DSL.second(nullRef))); - assertEquals(missingValue(), eval(DSL.second(missingRef))); - FunctionExpression expression = DSL.second(DSL.literal(new ExprTimeValue("01:02:03"))); assertEquals(INTEGER, expression.type()); assertEquals(integerValue(3), eval(expression)); @@ -1391,12 +1169,12 @@ public void second() { expression = DSL.second(DSL.literal(new ExprTimestampValue("2020-08-17 01:02:03"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(3), expression.valueOf(env)); + assertEquals(integerValue(3), expression.valueOf()); assertEquals("second(TIMESTAMP '2020-08-17 01:02:03')", expression.toString()); expression = DSL.second(DSL.literal(new ExprDatetimeValue("2020-08-17 01:02:03"))); assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(3), expression.valueOf(env)); + assertEquals(integerValue(3), expression.valueOf()); assertEquals("second(DATETIME '2020-08-17 01:02:03')", expression.toString()); } @@ -1436,9 +1214,6 @@ private static Stream getTestDataForSecondOfMinute() { @ParameterizedTest(name = "{2}") @MethodSource("getTestDataForSecondOfMinute") public void secondOfMinute(LiteralExpression arg, int expectedResult, String expectedString) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - secondOfMinuteQuery(DSL.second_of_minute(arg), expectedResult, expectedString); } @@ -1449,12 +1224,7 @@ private void invalidSecondOfMinuteQuery(String time) { @Test public void secondOfMinuteInvalidArguments() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertAll( - () -> assertEquals(nullValue(), eval(DSL.second_of_minute(nullRef))), - () -> assertEquals(missingValue(), eval(DSL.second_of_minute(missingRef))), //Invalid Seconds () -> assertThrows(SemanticCheckException.class, () -> invalidSecondOfMinuteQuery("12:23:61")), @@ -1470,14 +1240,8 @@ public void secondOfMinuteInvalidArguments() { ); } - @Test public void time_to_sec() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertEquals(nullValue(), eval(DSL.time_to_sec(nullRef))); - assertEquals(missingValue(), eval(DSL.time_to_sec(missingRef))); - FunctionExpression expression = DSL.time_to_sec(DSL.literal(new ExprTimeValue("22:23:00"))); assertEquals(LONG, expression.type()); assertEquals("time_to_sec(TIME '22:23:00')", expression.toString()); @@ -1491,11 +1255,6 @@ public void time_to_sec() { @Test public void time() { - when(nullRef.type()).thenReturn(TIME); - when(missingRef.type()).thenReturn(TIME); - assertEquals(nullValue(), eval(DSL.time(nullRef))); - assertEquals(missingValue(), eval(DSL.time(missingRef))); - FunctionExpression expr = DSL.time(DSL.literal("01:01:01")); assertEquals(TIME, expr.type()); assertEquals(new ExprTimeValue("01:01:01"), eval(expr)); @@ -1533,19 +1292,14 @@ public void time() { @Test public void timestamp() { - when(nullRef.type()).thenReturn(TIMESTAMP); - when(missingRef.type()).thenReturn(TIMESTAMP); - assertEquals(nullValue(), eval(DSL.timestamp(nullRef))); - assertEquals(missingValue(), eval(DSL.timestamp(missingRef))); - FunctionExpression expr = DSL.timestamp(DSL.literal("2020-08-17 01:01:01")); assertEquals(TIMESTAMP, expr.type()); - assertEquals(new ExprTimestampValue("2020-08-17 01:01:01"), expr.valueOf(env)); + assertEquals(new ExprTimestampValue("2020-08-17 01:01:01"), expr.valueOf()); assertEquals("timestamp(cast_to_timestamp(\"2020-08-17 01:01:01\"))", expr.toString()); expr = DSL.timestamp(DSL.literal(new ExprTimestampValue("2020-08-17 01:01:01"))); assertEquals(TIMESTAMP, expr.type()); - assertEquals(new ExprTimestampValue("2020-08-17 01:01:01"), expr.valueOf(env)); + assertEquals(new ExprTimestampValue("2020-08-17 01:01:01"), expr.valueOf()); assertEquals("timestamp(TIMESTAMP '2020-08-17 01:01:01')", expr.toString()); } @@ -1577,36 +1331,6 @@ private void weekOfYearQuery(String date, int mode, int expectedResult) { assertEquals(integerValue(expectedResult), eval(expression)); } - private void nullMissingWeekQuery(ExprCoreType date) { - when(nullRef.type()).thenReturn(date); - when(missingRef.type()).thenReturn(date); - assertEquals(nullValue(), eval(DSL.week(functionProperties, nullRef))); - assertEquals(missingValue(), eval(DSL.week(functionProperties, missingRef))); - } - - @Test - public void testNullMissingWeek() { - nullMissingWeekQuery(DATE); - nullMissingWeekQuery(DATETIME); - nullMissingWeekQuery(TIMESTAMP); - nullMissingWeekQuery(STRING); - - when(nullRef.type()).thenReturn(INTEGER); - when(missingRef.type()).thenReturn(INTEGER); - assertEquals(nullValue(), eval(DSL.week( - functionProperties, - DSL.literal("2019-01-05"), nullRef))); - assertEquals(missingValue(), eval(DSL.week( - functionProperties, - DSL.literal("2019-01-05"), missingRef))); - - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(INTEGER); - assertEquals(missingValue(), eval(DSL.week( - functionProperties, - nullRef, missingRef))); - } - private static Stream getTestDataForWeek() { //Test the behavior of different modes passed into the 'week_of_year' function return Stream.of( @@ -1646,8 +1370,6 @@ private static Stream getTestDataForWeek() { @ParameterizedTest(name = "{1}{2}") @MethodSource("getTestDataForWeek") public void testWeek(String date, int mode, int expected) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); weekQuery(date, mode, expected); weekOfYearQuery(date, mode, expected); weekOfYearUnderscoresQuery(date, mode, expected); @@ -1692,8 +1414,6 @@ public void testWeekFormats( LiteralExpression arg, String expectedString, Integer expectedInteger) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); validateStringFormat( DSL.week(functionProperties, arg), String.format("week(%s)", expectedString), expectedInteger); @@ -1707,9 +1427,6 @@ public void testWeekFormats( @Test public void testWeekOfYearWithTimeType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - assertAll( () -> validateStringFormat( DSL.week( @@ -1733,8 +1450,6 @@ public void testWeekOfYearWithTimeType() { @Test public void modeInUnsupportedFormat() { - nullMissingWeekQuery(DATE); - FunctionExpression expression1 = DSL .week(functionProperties, DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(8)); SemanticCheckException exception = @@ -1749,39 +1464,8 @@ public void modeInUnsupportedFormat() { exception.getMessage()); } - private void nullMissingWeekOfYearQuery(ExprCoreType date) { - when(nullRef.type()).thenReturn(date); - when(missingRef.type()).thenReturn(date); - assertEquals(nullValue(), eval(DSL.week_of_year( - functionProperties, - nullRef))); - assertEquals(missingValue(), eval(DSL.week_of_year( - functionProperties, - missingRef))); - } - @Test public void testInvalidWeekOfYear() { - nullMissingWeekOfYearQuery(DATE); - nullMissingWeekOfYearQuery(DATETIME); - nullMissingWeekOfYearQuery(TIMESTAMP); - nullMissingWeekOfYearQuery(STRING); - - when(nullRef.type()).thenReturn(INTEGER); - when(missingRef.type()).thenReturn(INTEGER); - assertEquals(nullValue(), eval(DSL.week_of_year( - functionProperties, - DSL.literal("2019-01-05"), nullRef))); - assertEquals(missingValue(), eval(DSL.week_of_year( - functionProperties, - DSL.literal("2019-01-05"), missingRef))); - - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(INTEGER); - assertEquals(missingValue(), eval(DSL.week_of_year( - functionProperties, - nullRef, missingRef))); - assertAll( //Test for WeekOfYear //test invalid month @@ -1815,8 +1499,6 @@ public void testInvalidWeekOfYear() { @Test public void weekOfYearModeInUnsupportedFormat() { - nullMissingWeekOfYearQuery(DATE); - FunctionExpression expression1 = DSL .week_of_year( functionProperties, @@ -1837,11 +1519,6 @@ public void weekOfYearModeInUnsupportedFormat() { @Test public void to_days() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.to_days(nullRef))); - assertEquals(missingValue(), eval(DSL.to_days(missingRef))); - FunctionExpression expression = DSL.to_days(DSL.literal(new ExprDateValue("2008-10-07"))); assertEquals(LONG, expression.type()); assertEquals("to_days(DATE '2008-10-07')", expression.toString()); @@ -1860,11 +1537,6 @@ public void to_days() { @Test public void year() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.year(nullRef))); - assertEquals(missingValue(), eval(DSL.year(missingRef))); - FunctionExpression expression = DSL.year(DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(INTEGER, expression.type()); assertEquals("year(DATE '2020-08-07')", expression.toString()); @@ -1896,58 +1568,6 @@ public void date_format() { DSL.literal(timestampFormat)); assertEquals(STRING, expr.type()); assertEquals(timestampFormatted, eval(expr).stringValue()); - - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.date_format( - functionProperties, - nullRef, - DSL.literal("")))); - assertEquals(missingValue(), eval(DSL.date_format( - functionProperties, - missingRef, - DSL.literal("")))); - - when(nullRef.type()).thenReturn(DATETIME); - when(missingRef.type()).thenReturn(DATETIME); - assertEquals(nullValue(), eval(DSL.date_format( - functionProperties, - nullRef, - DSL.literal("")))); - assertEquals(missingValue(), eval(DSL.date_format( - functionProperties, - missingRef, - DSL.literal("")))); - - when(nullRef.type()).thenReturn(TIMESTAMP); - when(missingRef.type()).thenReturn(TIMESTAMP); - assertEquals(nullValue(), eval(DSL.date_format( - functionProperties, - nullRef, - DSL.literal("")))); - assertEquals(missingValue(), eval(DSL.date_format( - functionProperties, - missingRef, - DSL.literal("")))); - - when(nullRef.type()).thenReturn(STRING); - when(missingRef.type()).thenReturn(STRING); - assertEquals(nullValue(), eval(DSL.date_format( - functionProperties, - nullRef, - DSL.literal("")))); - assertEquals(missingValue(), eval(DSL.date_format( - functionProperties, - missingRef, - DSL.literal("")))); - assertEquals(nullValue(), eval(DSL.date_format( - functionProperties, - DSL.literal(""), - nullRef))); - assertEquals(missingValue(), eval(DSL.date_format( - functionProperties, - DSL.literal(""), - missingRef))); } void testDateFormat(DateFormatTester dft) { @@ -1958,9 +1578,6 @@ void testDateFormat(DateFormatTester dft) { @Test public void testDateFormatWithTimeType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expr = DSL.date_format( functionProperties, DSL.literal(new ExprTimeValue("12:23:34")), @@ -1980,9 +1597,6 @@ public void testDateFormatWithTimeType() { @Test public void testTimeFormatWithDateType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expr = DSL.time_format( functionProperties, DSL.literal(new ExprDateValue("2023-01-16")), @@ -2076,9 +1690,6 @@ private void timeFormatQuery(LiteralExpression arg, public void testTimeFormat(LiteralExpression arg, LiteralExpression format, String expectedResult) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - timeFormatQuery(arg, format, expectedResult); } @@ -2105,8 +1716,6 @@ private static Stream getInvalidTestDataForTimeFormat() { @ParameterizedTest(name = "{0}{1}") @MethodSource("getInvalidTestDataForTimeFormat") public void testInvalidTimeFormat(LiteralExpression arg, LiteralExpression format) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expr = DSL.time_format(functionProperties, arg, format); assertThrows(SemanticCheckException.class, () -> eval(expr)); } @@ -2132,8 +1741,6 @@ private static Stream getInvalidTimeFormatHandlers() { @ParameterizedTest(name = "{0}") @MethodSource("getInvalidTimeFormatHandlers") public void testTimeFormatWithInvalidHandlers(String handler) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expr = DSL.time_format( functionProperties, DSL.literal("12:23:34"), @@ -2143,8 +1750,6 @@ public void testTimeFormatWithInvalidHandlers(String handler) { @Test public void testTimeFormatWithDateHandlers() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expr = DSL.time_format( functionProperties, DSL.literal(new ExprDateValue("2023-01-17")), @@ -2156,8 +1761,6 @@ public void testTimeFormatWithDateHandlers() { @Test public void testTimeFormatAndDateFormatReturnSameResult() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression timeFormatExpr = DSL.time_format( functionProperties, DSL.literal(new ExprDateValue("1998-01-31 13:14:15.012345")), @@ -2171,6 +1774,6 @@ public void testTimeFormatAndDateFormatReturnSameResult() { } private ExprValue eval(Expression expression) { - return expression.valueOf(env); + return expression.valueOf(); } } diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeTest.java index b5e184dbf0..22c3571aca 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeTest.java @@ -16,37 +16,25 @@ import java.time.format.DateTimeFormatter; import java.util.TimeZone; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import org.opensearch.sql.data.model.ExprDatetimeValue; -import org.opensearch.sql.data.model.ExprValue; import org.opensearch.sql.expression.DSL; -import org.opensearch.sql.expression.Expression; import org.opensearch.sql.expression.ExpressionTestBase; import org.opensearch.sql.expression.FunctionExpression; -import org.opensearch.sql.expression.env.Environment; - - -@ExtendWith(MockitoExtension.class) class DateTimeTest extends ExpressionTestBase { - @Mock - Environment env; - @Test public void noTimeZoneNoField2() { FunctionExpression expr = DSL.datetime(DSL.literal("2008-05-15 22:00:00")); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2008-05-15 22:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2008-05-15 22:00:00"), expr.valueOf()); } @Test public void positiveTimeZoneNoField2() { FunctionExpression expr = DSL.datetime(DSL.literal("2008-05-15 22:00:00+01:00")); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2008-05-15 22:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2008-05-15 22:00:00"), expr.valueOf()); } @Test @@ -54,7 +42,7 @@ public void positiveField1WrittenField2() { FunctionExpression expr = DSL.datetime(DSL.literal("2008-05-15 22:00:00+01:00"), DSL.literal("America/Los_Angeles")); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2008-05-15 14:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2008-05-15 14:00:00"), expr.valueOf()); } // When no timezone argument is passed inside the datetime field, it assumes local time. @@ -70,7 +58,7 @@ public void localDateTimeConversion() { FunctionExpression expr = DSL.datetime(DSL.literal(dt), DSL.literal(timeZone)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue(timeZoneLocal.toLocalDateTime()), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue(timeZoneLocal.toLocalDateTime()), expr.valueOf()); } @Test @@ -78,7 +66,7 @@ public void negativeField1WrittenField2() { FunctionExpression expr = DSL.datetime(DSL.literal("2008-05-15 22:00:00-11:00"), DSL.literal("America/Los_Angeles")); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2008-05-16 02:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2008-05-16 02:00:00"), expr.valueOf()); } @Test @@ -86,7 +74,7 @@ public void negativeField1PositiveField2() { FunctionExpression expr = DSL.datetime(DSL.literal("2008-05-15 22:00:00-12:00"), DSL.literal("+15:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -94,7 +82,7 @@ public void twentyFourHourDifference() { FunctionExpression expr = DSL.datetime(DSL.literal("2008-05-15 22:00:00-14:00"), DSL.literal("+10:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test @@ -102,13 +90,13 @@ public void negativeToNull() { FunctionExpression expr = DSL.datetime(DSL.literal("2008-05-15 22:00:00-11:00"), DSL.literal(nullValue())); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } @Test public void invalidDate() { FunctionExpression expr = DSL.datetime(DSL.literal("2008-04-31 22:00:00-11:00")); assertEquals(DATETIME, expr.type()); - assertEquals(nullValue(), expr.valueOf(env)); + assertEquals(nullValue(), expr.valueOf()); } } diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeTestBase.java b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeTestBase.java index 62d3fca1be..4c8d42e8f9 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeTestBase.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeTestBase.java @@ -15,8 +15,6 @@ import java.util.List; import org.opensearch.sql.data.model.ExprDateValue; import org.opensearch.sql.data.model.ExprDatetimeValue; -import org.opensearch.sql.data.model.ExprMissingValue; -import org.opensearch.sql.data.model.ExprNullValue; import org.opensearch.sql.data.model.ExprTimeValue; import org.opensearch.sql.data.model.ExprTimestampValue; import org.opensearch.sql.data.model.ExprValue; @@ -32,10 +30,6 @@ public class DateTimeTestBase extends ExpressionTestBase { protected final BuiltinFunctionRepository functionRepository = BuiltinFunctionRepository.getInstance(); - protected Expression nullRef = DSL.literal(ExprNullValue.of()); - - protected Expression missingRef = DSL.literal(ExprMissingValue.of()); - protected ExprValue eval(Expression expression) { return expression.valueOf(); } @@ -51,14 +45,13 @@ protected ExprValue adddate(Object first, Object interval) { } protected FunctionExpression addtime(Expression date, Expression interval) { - return (FunctionExpression) functionRepository.compile( - functionProperties, + return (FunctionExpression) functionRepository.compile(functionProperties, BuiltinFunctionName.ADDTIME.getName(), List.of(date, interval)); } protected ExprValue addtime(Temporal first, Temporal second) { return addtime(DSL.literal(fromObjectValue(first)), DSL.literal(fromObjectValue(second))) - .valueOf(null); + .valueOf(); } protected FunctionExpression date_add(Expression date, Expression interval) { @@ -82,14 +75,13 @@ protected ExprValue date_sub(Object first, Object second) { } protected FunctionExpression datediff(Expression first, Expression second) { - return (FunctionExpression) functionRepository.compile( - functionProperties, + return (FunctionExpression) functionRepository.compile(functionProperties, BuiltinFunctionName.DATEDIFF.getName(), List.of(first, second)); } protected Long datediff(Temporal first, Temporal second) { return datediff(DSL.literal(fromObjectValue(first)), DSL.literal(fromObjectValue(second))) - .valueOf(null).longValue(); + .valueOf().longValue(); } protected LocalDateTime fromUnixTime(Double value) { @@ -97,16 +89,13 @@ protected LocalDateTime fromUnixTime(Double value) { } protected FunctionExpression fromUnixTime(Expression value) { - return (FunctionExpression) - functionRepository.compile(functionProperties, - BuiltinFunctionName.FROM_UNIXTIME.getName(), List.of(value)); + return (FunctionExpression) functionRepository.compile(functionProperties, + BuiltinFunctionName.FROM_UNIXTIME.getName(), List.of(value)); } protected FunctionExpression fromUnixTime(Expression value, Expression format) { - return (FunctionExpression) - functionRepository.compile( - functionProperties, - BuiltinFunctionName.FROM_UNIXTIME.getName(), List.of(value, format)); + return (FunctionExpression) functionRepository.compile(functionProperties, + BuiltinFunctionName.FROM_UNIXTIME.getName(), List.of(value, format)); } protected LocalDateTime fromUnixTime(Long value) { @@ -124,10 +113,8 @@ protected String fromUnixTime(Double value, String format) { } protected FunctionExpression maketime(Expression hour, Expression minute, Expression second) { - return (FunctionExpression) - functionRepository.compile( - functionProperties, - BuiltinFunctionName.MAKETIME.getName(), List.of(hour, minute, second)); + return (FunctionExpression) functionRepository.compile(functionProperties, + BuiltinFunctionName.MAKETIME.getName(), List.of(hour, minute, second)); } protected LocalTime maketime(Double hour, Double minute, Double second) { @@ -136,18 +123,16 @@ protected LocalTime maketime(Double hour, Double minute, Double second) { } protected FunctionExpression makedate(Expression year, Expression dayOfYear) { - return (FunctionExpression) functionRepository.compile( - functionProperties, + return (FunctionExpression) functionRepository.compile(functionProperties, BuiltinFunctionName.MAKEDATE.getName(), List.of(year, dayOfYear)); } protected LocalDate makedate(double year, double dayOfYear) { - return makedate(DSL.literal(year), DSL.literal(dayOfYear)).valueOf(null).dateValue(); + return makedate(DSL.literal(year), DSL.literal(dayOfYear)).valueOf().dateValue(); } protected FunctionExpression period_add(Expression period, Expression months) { - return (FunctionExpression) functionRepository.compile( - functionProperties, + return (FunctionExpression) functionRepository.compile(functionProperties, BuiltinFunctionName.PERIOD_ADD.getName(), List.of(period, months)); } @@ -178,30 +163,28 @@ protected ExprValue subdate(Object first, Object interval) { } protected FunctionExpression subtime(Expression date, Expression interval) { - return (FunctionExpression) functionRepository.compile( - functionProperties, + return (FunctionExpression) functionRepository.compile(functionProperties, BuiltinFunctionName.SUBTIME.getName(), List.of(date, interval)); } protected ExprValue subtime(Temporal first, Temporal second) { return subtime(DSL.literal(fromObjectValue(first)), DSL.literal(fromObjectValue(second))) - .valueOf(null); + .valueOf(); } protected FunctionExpression timediff(Expression first, Expression second) { - return (FunctionExpression) functionRepository.compile( - functionProperties, + return (FunctionExpression) functionRepository.compile(functionProperties, BuiltinFunctionName.TIMEDIFF.getName(), List.of(first, second)); } protected LocalTime timediff(LocalTime first, LocalTime second) { return timediff(DSL.literal(new ExprTimeValue(first)), DSL.literal(new ExprTimeValue(second))) - .valueOf(null).timeValue(); + .valueOf().timeValue(); } protected FunctionExpression unixTimeStampExpr() { - return (FunctionExpression) functionRepository.compile( - functionProperties, BuiltinFunctionName.UNIX_TIMESTAMP.getName(), List.of()); + return (FunctionExpression) functionRepository.compile(functionProperties, + BuiltinFunctionName.UNIX_TIMESTAMP.getName(), List.of()); } protected Long unixTimeStamp() { @@ -209,9 +192,8 @@ protected Long unixTimeStamp() { } protected FunctionExpression unixTimeStampOf(Expression value) { - return (FunctionExpression) - functionRepository.compile(functionProperties, - BuiltinFunctionName.UNIX_TIMESTAMP.getName(), List.of(value)); + return (FunctionExpression) functionRepository.compile(functionProperties, + BuiltinFunctionName.UNIX_TIMESTAMP.getName(), List.of(value)); } protected Double unixTimeStampOf(Double value) { diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/MakeDateTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/MakeDateTest.java index 87cbc7ae48..fbd7e61c8d 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/MakeDateTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/MakeDateTest.java @@ -7,8 +7,6 @@ package org.opensearch.sql.expression.datetime; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.when; -import static org.opensearch.sql.data.model.ExprValueUtils.missingValue; import static org.opensearch.sql.data.model.ExprValueUtils.nullValue; import java.time.LocalDate; @@ -49,20 +47,6 @@ public void checkRounding() { assertEquals(LocalDate.of(43, 1, 2), makedate(42.50, 1.50)); } - @Test - public void checkNullValues() { - assertEquals(nullValue(), eval(makedate(nullRef, DSL.literal(42.)))); - assertEquals(nullValue(), eval(makedate(DSL.literal(42.), nullRef))); - assertEquals(nullValue(), eval(makedate(nullRef, nullRef))); - } - - @Test - public void checkMissingValues() { - assertEquals(missingValue(), eval(makedate(missingRef, DSL.literal(42.)))); - assertEquals(missingValue(), eval(makedate(DSL.literal(42.), missingRef))); - assertEquals(missingValue(), eval(makedate(missingRef, missingRef))); - } - private static Stream getTestData() { return Stream.of( Arguments.of(3755.421154, 9.300720), diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/MakeTimeTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/MakeTimeTest.java index 3fb2472c18..2f8e45b4c3 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/MakeTimeTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/MakeTimeTest.java @@ -8,8 +8,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.when; -import static org.opensearch.sql.data.model.ExprValueUtils.missingValue; import static org.opensearch.sql.data.model.ExprValueUtils.nullValue; import java.time.Duration; @@ -56,28 +54,6 @@ public void checkSecondFraction() { assertEquals(LocalTime.of(0, 0, 0).withNano(100502000), maketime(0., 0., 0.100502)); } - @Test - public void checkNullValues() { - assertEquals(nullValue(), eval(maketime(nullRef, DSL.literal(42.), DSL.literal(42.)))); - assertEquals(nullValue(), eval(maketime(DSL.literal(42.), nullRef, DSL.literal(42.)))); - assertEquals(nullValue(), eval(maketime(DSL.literal(42.), DSL.literal(42.), nullRef))); - assertEquals(nullValue(), eval(maketime(nullRef, nullRef, DSL.literal(42.)))); - assertEquals(nullValue(), eval(maketime(nullRef, DSL.literal(42.), nullRef))); - assertEquals(nullValue(), eval(maketime(nullRef, nullRef, nullRef))); - assertEquals(nullValue(), eval(maketime(DSL.literal(42.), nullRef, nullRef))); - } - - @Test - public void checkMissingValues() { - assertEquals(missingValue(), eval(maketime(missingRef, DSL.literal(42.), DSL.literal(42.)))); - assertEquals(missingValue(), eval(maketime(DSL.literal(42.), missingRef, DSL.literal(42.)))); - assertEquals(missingValue(), eval(maketime(DSL.literal(42.), DSL.literal(42.), missingRef))); - assertEquals(missingValue(), eval(maketime(missingRef, missingRef, DSL.literal(42.)))); - assertEquals(missingValue(), eval(maketime(missingRef, DSL.literal(42.), missingRef))); - assertEquals(missingValue(), eval(maketime(missingRef, missingRef, missingRef))); - assertEquals(missingValue(), eval(maketime(DSL.literal(42.), missingRef, missingRef))); - } - private static Stream getTestData() { return Stream.of( Arguments.of(20., 30., 40.), diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/NowLikeFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/NowLikeFunctionTest.java index 4b8a4aac5e..b67f4efc21 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/NowLikeFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/NowLikeFunctionTest.java @@ -9,24 +9,20 @@ import static org.hamcrest.MatcherAssert.assertThat; 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.DATE; import static org.opensearch.sql.data.type.ExprCoreType.DATETIME; import static org.opensearch.sql.data.type.ExprCoreType.TIME; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; -import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.Period; -import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; import java.time.temporal.TemporalUnit; import java.util.List; import java.util.TimeZone; -import java.util.concurrent.Callable; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; @@ -128,7 +124,7 @@ private static LocalDateTime utcDateTimeNow(FunctionProperties functionPropertie ZonedDateTime zonedDateTime = LocalDateTime.now(functionProperties.getQueryStartClock()) .atZone(TimeZone.getDefault().toZoneId()); - return zonedDateTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); + return zonedDateTime.withZoneSameInstant(UTC_ZONE_ID).toLocalDateTime(); } /** diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/TimestampTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/TimestampTest.java index 6e939cd6be..957dac5c74 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/TimestampTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/TimestampTest.java @@ -8,6 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import java.time.Instant; import java.time.LocalDate; @@ -66,7 +67,7 @@ public void timestamp_one_arg_time() { var expr = DSL.timestamp(functionProperties, DSL.time(DSL.literal("22:33:44"))); assertEquals(TIMESTAMP, expr.type()); var refValue = LocalDate.now().atTime(LocalTime.of(22, 33, 44)) - .atZone(ExprTimestampValue.ZONE).toInstant(); + .atZone(UTC_ZONE_ID).toInstant(); assertEquals(new ExprTimestampValue(refValue), expr.valueOf()); } @@ -75,7 +76,7 @@ public void timestamp_one_arg_date() { var expr = DSL.timestamp(functionProperties, DSL.date(DSL.literal("2077-12-15"))); assertEquals(TIMESTAMP, expr.type()); var refValue = LocalDate.of(2077, 12, 15).atStartOfDay() - .atZone(ExprTimestampValue.ZONE).toInstant(); + .atZone(UTC_ZONE_ID).toInstant(); assertEquals(new ExprTimestampValue(refValue), expr.valueOf()); } @@ -96,7 +97,7 @@ public void timestamp_one_arg_timestamp() { } private static Instant dateTime2Instant(LocalDateTime dt) { - return dt.atZone(ExprTimestampValue.ZONE).toInstant(); + return dt.atZone(UTC_ZONE_ID).toInstant(); } private static ExprTimestampValue dateTime2ExprTs(LocalDateTime dt) { diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/UnixTwoWayConversionTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/UnixTwoWayConversionTest.java index cb4d318eb3..70fe299e97 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/UnixTwoWayConversionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/UnixTwoWayConversionTest.java @@ -7,9 +7,9 @@ package org.opensearch.sql.expression.datetime; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID; import java.time.LocalDateTime; -import java.time.ZoneId; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -34,7 +34,7 @@ public void checkConvertNow_with_eval() { private LocalDateTime getExpectedNow() { return LocalDateTime.now( - functionProperties.getQueryStartClock().withZone(ZoneId.of("UTC"))) + functionProperties.getQueryStartClock().withZone(UTC_ZONE_ID)) .withNano(0); } diff --git a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/ArithmeticFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/ArithmeticFunctionTest.java index fc3c0bce8f..b28bea8b89 100644 --- a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/ArithmeticFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/ArithmeticFunctionTest.java @@ -9,19 +9,11 @@ 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.config.TestConfig.INT_TYPE_MISSING_VALUE_FIELD; -import static org.opensearch.sql.config.TestConfig.INT_TYPE_NULL_VALUE_FIELD; -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.data.model.ExprValueUtils.integerValue; -import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; import static org.opensearch.sql.expression.DSL.literal; -import static org.opensearch.sql.expression.DSL.ref; import com.google.common.collect.Lists; import java.util.Arrays; import java.util.List; -import java.util.function.Function; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -41,7 +33,6 @@ import org.opensearch.sql.data.type.WideningTypeRule; import org.opensearch.sql.exception.ExpressionEvaluationException; import org.opensearch.sql.expression.DSL; -import org.opensearch.sql.expression.Expression; import org.opensearch.sql.expression.ExpressionTestBase; import org.opensearch.sql.expression.FunctionExpression; import org.opensearch.sql.expression.function.BuiltinFunctionName; @@ -66,71 +57,6 @@ private static Stream arithmeticOperatorArguments() { BuiltinFunctionName.DIVIDE, BuiltinFunctionName.DIVIDE).map(Arguments::of); } - @ParameterizedTest(name = "{0}(int,null)") - @MethodSource("arithmeticOperatorArguments") - public void arithmetic_int_null(BuiltinFunctionName builtinFunctionName) { - Function< - List, FunctionExpression> function = functionMapping(builtinFunctionName); - - FunctionExpression functionExpression = - function.apply(Arrays.asList(literal(integerValue(1)), - ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER))); - assertEquals(INTEGER, functionExpression.type()); - assertEquals(LITERAL_NULL, functionExpression.valueOf(valueEnv())); - - functionExpression = function.apply( - Arrays.asList(ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), literal(integerValue(1)))); - assertEquals(INTEGER, functionExpression.type()); - assertEquals(LITERAL_NULL, functionExpression.valueOf(valueEnv())); - } - - @ParameterizedTest(name = "{0}(int,missing)") - @MethodSource("arithmeticOperatorArguments") - public void arithmetic_int_missing(BuiltinFunctionName builtinFunctionName) { - Function< - List, FunctionExpression> function = functionMapping(builtinFunctionName); - FunctionExpression functionExpression = - function.apply(Arrays.asList(literal(integerValue(1)), - ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER))); - assertEquals(INTEGER, functionExpression.type()); - assertEquals(LITERAL_MISSING, functionExpression.valueOf(valueEnv())); - - functionExpression = function.apply(Arrays.asList(ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - literal(integerValue(1)))); - assertEquals(INTEGER, functionExpression.type()); - assertEquals(LITERAL_MISSING, functionExpression.valueOf(valueEnv())); - } - - @ParameterizedTest(name = "{0}(null,missing)") - @MethodSource("arithmeticOperatorArguments") - public void arithmetic_null_missing(BuiltinFunctionName builtinFunctionName) { - Function< - List, FunctionExpression> function = functionMapping(builtinFunctionName); - FunctionExpression functionExpression = function.apply( - Arrays.asList(ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER))); - assertEquals(INTEGER, functionExpression.type()); - assertEquals(LITERAL_NULL, functionExpression.valueOf(valueEnv())); - - functionExpression = function.apply( - Arrays.asList(ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER))); - assertEquals(INTEGER, functionExpression.type()); - assertEquals(LITERAL_MISSING, functionExpression.valueOf(valueEnv())); - - functionExpression = function.apply( - Arrays.asList(ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER))); - assertEquals(INTEGER, functionExpression.type()); - assertEquals(LITERAL_MISSING, functionExpression.valueOf(valueEnv())); - - functionExpression = function.apply( - Arrays.asList(ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER))); - assertEquals(INTEGER, functionExpression.type()); - assertEquals(LITERAL_MISSING, functionExpression.valueOf(valueEnv())); - } - @ParameterizedTest(name = "add({1}, {2})") @MethodSource("arithmeticFunctionArguments") public void add(ExprValue op1, ExprValue op2) { diff --git a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java index 161883fc28..d9f95bc67a 100644 --- a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java @@ -12,12 +12,6 @@ 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.config.TestConfig.DOUBLE_TYPE_MISSING_VALUE_FIELD; -import static org.opensearch.sql.config.TestConfig.DOUBLE_TYPE_NULL_VALUE_FIELD; -import static org.opensearch.sql.config.TestConfig.INT_TYPE_MISSING_VALUE_FIELD; -import static org.opensearch.sql.config.TestConfig.INT_TYPE_NULL_VALUE_FIELD; -import static org.opensearch.sql.config.TestConfig.STRING_TYPE_MISSING_VALUE_FIELD; -import static org.opensearch.sql.config.TestConfig.STRING_TYPE_NULL_VALUE_FIELD; import static org.opensearch.sql.data.model.ExprValueUtils.getDoubleValue; import static org.opensearch.sql.data.model.ExprValueUtils.getFloatValue; import static org.opensearch.sql.data.type.ExprCoreType.BYTE; @@ -177,17 +171,6 @@ public void abs_short_value(Short value) { assertEquals(String.format("abs(%s)", value.toString()), abs.toString()); } - @Test - public void abs_null_value() { - assertTrue(DSL.abs(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)).valueOf(valueEnv()).isNull()); - } - - @Test - public void abs_missing_value() { - assertTrue( - DSL.abs(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)).valueOf(valueEnv()).isMissing()); - } - /** * Test ceil/ceiling with integer value. */ @@ -274,34 +257,6 @@ public void ceil_double_value(Double value) { assertEquals(String.format("ceiling(%s)", value.toString()), ceiling.toString()); } - /** - * Test ceil/ceiling with null value. - */ - @Test - public void ceil_null_value() { - FunctionExpression ceil = DSL.ceil(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(LONG, ceil.type()); - assertTrue(ceil.valueOf(valueEnv()).isNull()); - - FunctionExpression ceiling = DSL.ceiling(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(LONG, ceiling.type()); - assertTrue(ceiling.valueOf(valueEnv()).isNull()); - } - - /** - * Test ceil/ceiling with missing value. - */ - @Test - public void ceil_missing_value() { - FunctionExpression ceil = DSL.ceil(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(LONG, ceil.type()); - assertTrue(ceil.valueOf(valueEnv()).isMissing()); - - FunctionExpression ceiling = DSL.ceiling(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(LONG, ceiling.type()); - assertTrue(ceiling.valueOf(valueEnv()).isMissing()); - } - /** * Test conv from decimal base with string as a number. */ @@ -402,59 +357,6 @@ public void conv_to_decimal(Integer value) { assertEquals(String.format("conv(%s, 16, 10)", value), conv.toString()); } - /** - * Test conv with null value. - */ - @Test - public void conv_null_value() { - FunctionExpression conv = DSL.conv( - DSL.ref(STRING_TYPE_NULL_VALUE_FIELD, STRING), DSL.literal(10), DSL.literal(2)); - assertEquals(STRING, conv.type()); - assertTrue(conv.valueOf(valueEnv()).isNull()); - - conv = DSL.conv( - DSL.literal("1"), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(2)); - assertEquals(STRING, conv.type()); - assertTrue(conv.valueOf(valueEnv()).isNull()); - - conv = DSL.conv( - DSL.literal("1"), DSL.literal(10), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(STRING, conv.type()); - assertTrue(conv.valueOf(valueEnv()).isNull()); - } - - /** - * Test conv with missing value. - */ - @Test - public void conv_missing_value() { - FunctionExpression conv = DSL.conv( - DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING), DSL.literal(10), DSL.literal(2)); - assertEquals(STRING, conv.type()); - assertTrue(conv.valueOf(valueEnv()).isMissing()); - - conv = DSL.conv( - DSL.literal("1"), DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(2)); - assertEquals(STRING, conv.type()); - assertTrue(conv.valueOf(valueEnv()).isMissing()); - - conv = DSL.conv( - DSL.literal("1"), DSL.literal(10), DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(STRING, conv.type()); - assertTrue(conv.valueOf(valueEnv()).isMissing()); - } - - /** - * Test conv with null and missing values. - */ - @Test - public void conv_null_missing() { - FunctionExpression conv = DSL.conv(DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(2)); - assertEquals(STRING, conv.type()); - assertTrue(conv.valueOf(valueEnv()).isMissing()); - } - /** * Test crc32 with string value. */ @@ -470,26 +372,6 @@ public void crc32_string_value(String value) { assertEquals(String.format("crc32(\"%s\")", value), crc.toString()); } - /** - * Test crc32 with null value. - */ - @Test - public void crc32_null_value() { - FunctionExpression crc = DSL.crc32(DSL.ref(STRING_TYPE_NULL_VALUE_FIELD, STRING)); - assertEquals(LONG, crc.type()); - assertTrue(crc.valueOf(valueEnv()).isNull()); - } - - /** - * Test crc32 with missing value. - */ - @Test - public void crc32_missing_value() { - FunctionExpression crc = DSL.crc32(DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING)); - assertEquals(LONG, crc.type()); - assertTrue(crc.valueOf(valueEnv()).isMissing()); - } - /** * Test constant e. */ @@ -551,26 +433,6 @@ public void exp_double_value(Double value) { assertEquals(String.format("exp(%s)", value.toString()), exp.toString()); } - /** - * Test exp with null value. - */ - @Test - public void exp_null_value() { - FunctionExpression exp = DSL.exp(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, exp.type()); - assertTrue(exp.valueOf(valueEnv()).isNull()); - } - - /** - * Test exp with missing value. - */ - @Test - public void exp_missing_value() { - FunctionExpression exp = DSL.exp(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, exp.type()); - assertTrue(exp.valueOf(valueEnv()).isMissing()); - } - /** * Test expm1 with integer value. */ @@ -707,26 +569,6 @@ public void floor_double_value(Double value) { assertEquals(String.format("floor(%s)", value.toString()), floor.toString()); } - /** - * Test floor with null value. - */ - @Test - public void floor_null_value() { - FunctionExpression floor = DSL.floor(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(LONG, floor.type()); - assertTrue(floor.valueOf(valueEnv()).isNull()); - } - - /** - * Test floor with missing value. - */ - @Test - public void floor_missing_value() { - FunctionExpression floor = DSL.floor(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(LONG, floor.type()); - assertTrue(floor.valueOf(valueEnv()).isMissing()); - } - /** * Test ln with integer value. */ @@ -790,26 +632,6 @@ public void ln_invalid_value(Double value) { assertTrue(ln.valueOf(valueEnv()).isNull()); } - /** - * Test ln with null value. - */ - @Test - public void ln_null_value() { - FunctionExpression ln = DSL.ln(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, ln.type()); - assertTrue(ln.valueOf(valueEnv()).isNull()); - } - - /** - * Test ln with missing value. - */ - @Test - public void ln_missing_value() { - FunctionExpression ln = DSL.ln(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, ln.type()); - assertTrue(ln.valueOf(valueEnv()).isMissing()); - } - /** * Test log with 1 int argument. */ @@ -881,28 +703,6 @@ public void log_invalid_value(Double value) { assertTrue(log.valueOf(valueEnv()).isNull()); } - /** - * Test log with 1 null value argument. - */ - @Test - public void log_null_value() { - FunctionExpression log = DSL.log( - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isNull()); - } - - /** - * Test log with 1 missing value argument. - */ - @Test - public void log_missing_value() { - FunctionExpression log = DSL.log( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isMissing()); - } - /** * Test log with 2 int arguments. */ @@ -970,66 +770,6 @@ public void log_two_invalid_double_value(Double v1, Double v2) { assertTrue(log.valueOf(valueEnv()).isNull()); } - /** - * Test log with 2 null value arguments. - */ - @Test - public void log_two_null_value() { - FunctionExpression log = DSL.log( - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), DSL.literal(2D)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isNull()); - - log = DSL.log(DSL.literal(2D), DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isNull()); - - log = DSL.log( - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isNull()); - } - - /** - * Test log with 2 missing value arguments. - */ - @Test - public void log_two_missing_value() { - FunctionExpression log = DSL.log( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), DSL.literal(2D)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isMissing()); - - log = DSL.log(DSL.literal(2D), DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isMissing()); - - log = DSL.log( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isMissing()); - } - - /** - * Test log with null and missing value arguments. - */ - @Test - public void log_null_missing() { - FunctionExpression log = DSL.log( - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isMissing()); - - log = DSL.log( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isMissing()); - } - /** * Test log10 with int value. */ @@ -1101,28 +841,6 @@ public void log10_two_invalid_value(Double v) { assertTrue(log.valueOf(valueEnv()).isNull()); } - /** - * Test log10 with null value. - */ - @Test - public void log10_null_value() { - FunctionExpression log = DSL.log10( - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isNull()); - } - - /** - * Test log10 with missing value. - */ - @Test - public void log10_missing_value() { - FunctionExpression log = DSL.log10( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isMissing()); - } - /** * Test log2 with int value. */ @@ -1195,25 +913,108 @@ public void log2_invalid_double_value(Double v) { } /** - * Test log2 with null value. + * Test mod with byte value. */ - @Test - public void log2_null_value() { - FunctionExpression log = DSL.log2( - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isNull()); + @ParameterizedTest(name = "mod({0}, {1})") + @MethodSource("testLogByteArguments") + public void mod_byte_value(Byte v1, Byte v2) { + FunctionExpression mod = DSL.mod(DSL.literal(v1), DSL.literal(v2)); + + assertThat( + mod.valueOf(valueEnv()), + allOf(hasType(BYTE), hasValue(Integer.valueOf(v1 % v2).byteValue()))); + assertEquals(String.format("mod(%s, %s)", v1, v2), mod.toString()); + + mod = DSL.mod(DSL.literal(v1), DSL.literal(new ExprByteValue(0))); + assertEquals(BYTE, mod.type()); + assertTrue(mod.valueOf(valueEnv()).isNull()); } /** - * Test log2 with missing value. + * Test mod with short value. */ - @Test - public void log2_missing_value() { - FunctionExpression log = DSL.log2( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, log.type()); - assertTrue(log.valueOf(valueEnv()).isMissing()); + @ParameterizedTest(name = "mod({0}, {1})") + @MethodSource("testLogShortArguments") + public void mod_short_value(Short v1, Short v2) { + FunctionExpression mod = DSL.mod(DSL.literal(v1), DSL.literal(v2)); + + assertThat( + mod.valueOf(valueEnv()), + allOf(hasType(SHORT), + hasValue(Integer.valueOf(v1 % v2).shortValue()))); + assertEquals(String.format("mod(%s, %s)", v1, v2), mod.toString()); + + mod = DSL.mod(DSL.literal(v1), DSL.literal(new ExprShortValue(0))); + assertEquals(SHORT, mod.type()); + assertTrue(mod.valueOf(valueEnv()).isNull()); + } + + /** + * Test mod with integer value. + */ + @ParameterizedTest(name = "mod({0}, {1})") + @MethodSource("testLogIntegerArguments") + public void mod_int_value(Integer v1, Integer v2) { + FunctionExpression mod = DSL.mod(DSL.literal(v1), DSL.literal(v2)); + assertThat( + mod.valueOf(valueEnv()), + allOf(hasType(INTEGER), hasValue(v1 % v2))); + assertEquals(String.format("mod(%s, %s)", v1, v2), mod.toString()); + + mod = DSL.mod(DSL.literal(v1), DSL.literal(0)); + assertEquals(INTEGER, mod.type()); + assertTrue(mod.valueOf(valueEnv()).isNull()); + } + + /** + * Test mod with long value. + */ + @ParameterizedTest(name = "mod({0}, {1})") + @MethodSource("testLogLongArguments") + public void mod_long_value(Long v1, Long v2) { + FunctionExpression mod = DSL.mod(DSL.literal(v1), DSL.literal(v2)); + assertThat( + mod.valueOf(valueEnv()), + allOf(hasType(LONG), hasValue(v1 % v2))); + assertEquals(String.format("mod(%s, %s)", v1, v2), mod.toString()); + + mod = DSL.mod(DSL.literal(v1), DSL.literal(0)); + assertEquals(LONG, mod.type()); + assertTrue(mod.valueOf(valueEnv()).isNull()); + } + + /** + * Test mod with long value. + */ + @ParameterizedTest(name = "mod({0}, {1})") + @MethodSource("testLogFloatArguments") + public void mod_float_value(Float v1, Float v2) { + FunctionExpression mod = DSL.mod(DSL.literal(v1), DSL.literal(v2)); + assertThat( + mod.valueOf(valueEnv()), + allOf(hasType(FLOAT), hasValue(v1 % v2))); + assertEquals(String.format("mod(%s, %s)", v1, v2), mod.toString()); + + mod = DSL.mod(DSL.literal(v1), DSL.literal(0)); + assertEquals(FLOAT, mod.type()); + assertTrue(mod.valueOf(valueEnv()).isNull()); + } + + /** + * Test mod with double value. + */ + @ParameterizedTest(name = "mod({0}, {1})") + @MethodSource("testLogDoubleArguments") + public void mod_double_value(Double v1, Double v2) { + FunctionExpression mod = DSL.mod(DSL.literal(v1), DSL.literal(v2)); + assertThat( + mod.valueOf(valueEnv()), + allOf(hasType(DOUBLE), hasValue(v1 % v2))); + assertEquals(String.format("mod(%s, %s)", v1, v2), mod.toString()); + + mod = DSL.mod(DSL.literal(v1), DSL.literal(0)); + assertEquals(DOUBLE, mod.type()); + assertTrue(mod.valueOf(valueEnv()).isNull()); } /** @@ -1312,103 +1113,6 @@ public void pow_double_value(Double v1, Double v2) { assertEquals(String.format("pow(%s, %s)", v1, v2), pow.toString()); } - /** - * Test pow/power with null value. - */ - @Test - public void pow_null_value() { - FunctionExpression pow = DSL.pow(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(DOUBLE, pow.type()); - assertTrue(pow.valueOf(valueEnv()).isNull()); - - DSL.pow(DSL.literal(1), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, pow.type()); - assertTrue(pow.valueOf(valueEnv()).isNull()); - - DSL.pow( - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, pow.type()); - assertTrue(pow.valueOf(valueEnv()).isNull()); - - FunctionExpression power = - DSL.power(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(DOUBLE, power.type()); - assertTrue(power.valueOf(valueEnv()).isNull()); - - power = DSL.power(DSL.literal(1), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, power.type()); - assertTrue(power.valueOf(valueEnv()).isNull()); - - power = DSL.power( - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, power.type()); - assertTrue(power.valueOf(valueEnv()).isNull()); - } - - /** - * Test pow/power with missing value. - */ - @Test - public void pow_missing_value() { - FunctionExpression pow = - DSL.pow(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(DOUBLE, pow.type()); - assertTrue(pow.valueOf(valueEnv()).isMissing()); - - DSL.pow(DSL.literal(1), DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, pow.type()); - assertTrue(pow.valueOf(valueEnv()).isMissing()); - - DSL.pow(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, pow.type()); - assertTrue(pow.valueOf(valueEnv()).isMissing()); - - FunctionExpression power = - DSL.power(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(DOUBLE, power.type()); - assertTrue(power.valueOf(valueEnv()).isMissing()); - - power = DSL.power(DSL.literal(1), DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, power.type()); - assertTrue(power.valueOf(valueEnv()).isMissing()); - - power = DSL.power(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, power.type()); - assertTrue(power.valueOf(valueEnv()).isMissing()); - } - - /** - * Test pow/power with null and missing values. - */ - @Test - public void pow_null_missing() { - FunctionExpression pow = DSL.pow( - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, pow.type()); - assertTrue(pow.valueOf(valueEnv()).isMissing()); - - pow = DSL.pow( - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, pow.type()); - assertTrue(pow.valueOf(valueEnv()).isMissing()); - - FunctionExpression power = DSL.power( - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, power.type()); - assertTrue(power.valueOf(valueEnv()).isMissing()); - - power = DSL.power( - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, power.type()); - assertTrue(power.valueOf(valueEnv()).isMissing()); - } - /** * Test pow/power with null output. */ @@ -1653,60 +1357,6 @@ public void round_double_value(Double value) { assertEquals(String.format("round(%s, -1)", value), round.toString()); } - /** - * Test round with null value. - */ - @Test - public void round_null_value() { - FunctionExpression round = DSL.round(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(LONG, round.type()); - assertTrue(round.valueOf(valueEnv()).isNull()); - - round = DSL.round(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(LONG, round.type()); - assertTrue(round.valueOf(valueEnv()).isNull()); - - round = DSL.round(DSL.literal(1), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(LONG, round.type()); - assertTrue(round.valueOf(valueEnv()).isNull()); - } - - /** - * Test round with null value. - */ - @Test - public void round_missing_value() { - FunctionExpression round = DSL.round(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(LONG, round.type()); - assertTrue(round.valueOf(valueEnv()).isMissing()); - - round = DSL.round(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(LONG, round.type()); - assertTrue(round.valueOf(valueEnv()).isMissing()); - - round = DSL.round(DSL.literal(1), DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(LONG, round.type()); - assertTrue(round.valueOf(valueEnv()).isMissing()); - } - - /** - * Test round with null and missing values. - */ - @Test - public void round_null_missing() { - FunctionExpression round = DSL.round( - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(LONG, round.type()); - assertTrue(round.valueOf(valueEnv()).isMissing()); - - round = DSL.round( - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(LONG, round.type()); - assertTrue(round.valueOf(valueEnv()).isMissing()); - } - /** * Test sign with integer value. */ @@ -1759,26 +1409,6 @@ public void sign_double_value(Double value) { assertEquals(String.format("sign(%s)", value), sign.toString()); } - /** - * Test sign with null value. - */ - @Test - public void sign_null_value() { - FunctionExpression sign = DSL.sign(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(INTEGER, sign.type()); - assertTrue(sign.valueOf(valueEnv()).isNull()); - } - - /** - * Test sign with missing value. - */ - @Test - public void sign_missing_value() { - FunctionExpression sign = DSL.sign(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(INTEGER, sign.type()); - assertTrue(sign.valueOf(valueEnv()).isMissing()); - } - /** * Test signum with byte value. */ @@ -1978,26 +1608,6 @@ public void sqrt_negative_value(Double value) { assertTrue(sqrt.valueOf(valueEnv()).isNull()); } - /** - * Test sqrt with null value. - */ - @Test - public void sqrt_null_value() { - FunctionExpression sqrt = DSL.sqrt(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, sqrt.type()); - assertTrue(sqrt.valueOf(valueEnv()).isNull()); - } - - /** - * Test sqrt with missing value. - */ - @Test - public void sqrt_missing_value() { - FunctionExpression sqrt = DSL.sqrt(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, sqrt.type()); - assertTrue(sqrt.valueOf(valueEnv()).isMissing()); - } - /** * Test truncate with integer value. */ @@ -2053,63 +1663,6 @@ public void truncate_double_value(Double value) { assertEquals(String.format("truncate(%s, 1)", value), truncate.toString()); } - /** - * Test truncate with null value. - */ - @Test - public void truncate_null_value() { - FunctionExpression truncate = - DSL.truncate(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(LONG, truncate.type()); - assertTrue(truncate.valueOf(valueEnv()).isNull()); - - truncate = DSL.truncate(DSL.literal(1), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(LONG, truncate.type()); - assertTrue(truncate.valueOf(valueEnv()).isNull()); - - truncate = DSL.truncate( - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(LONG, truncate.type()); - assertTrue(truncate.valueOf(valueEnv()).isNull()); - } - - /** - * Test truncate with missing value. - */ - @Test - public void truncate_missing_value() { - FunctionExpression truncate = - DSL.truncate(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(LONG, truncate.type()); - assertTrue(truncate.valueOf(valueEnv()).isMissing()); - - truncate = DSL.truncate(DSL.literal(1), DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(LONG, truncate.type()); - assertTrue(truncate.valueOf(valueEnv()).isMissing()); - - truncate = DSL.truncate( - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(LONG, truncate.type()); - assertTrue(truncate.valueOf(valueEnv()).isMissing()); - } - - /** - * Test truncate with null and missing values. - */ - @Test - public void truncate_null_missing() { - FunctionExpression truncate = DSL.truncate(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(LONG, truncate.type()); - assertTrue(truncate.valueOf(valueEnv()).isMissing()); - - truncate = DSL.truncate(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(LONG, truncate.type()); - assertTrue(truncate.valueOf(valueEnv()).isMissing()); - } - /** * Test constant pi. */ @@ -2147,13 +1700,6 @@ public void rand_int_value(Integer n) { assertEquals(String.format("rand(%s)", n), rand.toString()); } - @Test - public void rand_null_value() { - FunctionExpression rand = DSL.rand(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(FLOAT, rand.type()); - assertTrue(rand.valueOf(valueEnv()).isNull()); - } - /** * Test acos with integer, long, float, double values. */ @@ -2178,26 +1724,6 @@ public void acos_with_illegal_value(Number value) { assertTrue(acos.valueOf(valueEnv()).isNull()); } - /** - * Test acos with null value. - */ - @Test - public void acos_null_value() { - FunctionExpression acos = DSL.acos(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, acos.type()); - assertTrue(acos.valueOf(valueEnv()).isNull()); - } - - /** - * Test acos with missing value. - */ - @Test - public void acos_missing_value() { - FunctionExpression acos = DSL.acos(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, acos.type()); - assertTrue(acos.valueOf(valueEnv()).isMissing()); - } - /** * Test asin with integer, long, float, double values. */ @@ -2222,26 +1748,6 @@ public void asin_with_illegal_value(Number value) { assertTrue(asin.valueOf(valueEnv()).isNull()); } - /** - * Test asin with null value. - */ - @Test - public void asin_null_value() { - FunctionExpression asin = DSL.asin(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, asin.type()); - assertTrue(asin.valueOf(valueEnv()).isNull()); - } - - /** - * Test asin with missing value. - */ - @Test - public void asin_missing_value() { - FunctionExpression asin = DSL.asin(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, asin.type()); - assertTrue(asin.valueOf(valueEnv()).isMissing()); - } - /** * Test atan with one argument integer, long, float, double values. */ @@ -2269,69 +1775,6 @@ public void atan_two_args(Number v1, Number v2) { assertEquals(String.format("atan(%s, %s)", v1, v2), atan.toString()); } - /** - * Test atan with null value. - */ - @Test - public void atan_null_value() { - FunctionExpression atan = DSL.atan(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isNull()); - - atan = DSL.atan(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), DSL.literal(1)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isNull()); - - atan = DSL.atan(DSL.literal(1), DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isNull()); - - atan = DSL.atan(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isNull()); - } - - /** - * Test atan with missing value. - */ - @Test - public void atan_missing_value() { - FunctionExpression atan = DSL.atan(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isMissing()); - - atan = DSL.atan(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), DSL.literal(1)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isMissing()); - - atan = DSL.atan(DSL.literal(1), DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isMissing()); - - atan = DSL.atan(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isMissing()); - } - - /** - * Test atan with missing value. - */ - @Test - public void atan_null_missing() { - FunctionExpression atan = DSL.atan( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isMissing()); - - atan = DSL.atan(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan.type()); - assertTrue(atan.valueOf(valueEnv()).isMissing()); - } - /** * Test atan2 with integer, long, float, double values. */ @@ -2345,63 +1788,6 @@ public void test_atan2(Number v1, Number v2) { assertEquals(String.format("atan2(%s, %s)", v1, v2), atan2.toString()); } - /** - * Test atan2 with null value. - */ - @Test - public void atan2_null_value() { - FunctionExpression atan2 = DSL.atan2( - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), DSL.literal(1)); - assertEquals(DOUBLE, atan2.type()); - assertTrue(atan2.valueOf(valueEnv()).isNull()); - - atan2 = DSL.atan2(DSL.literal(1), DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan2.type()); - assertTrue(atan2.valueOf(valueEnv()).isNull()); - - atan2 = DSL.atan2(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan2.type()); - assertTrue(atan2.valueOf(valueEnv()).isNull()); - } - - /** - * Test atan2 with missing value. - */ - @Test - public void atan2_missing_value() { - FunctionExpression atan2 = DSL.atan2( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), DSL.literal(1)); - assertEquals(DOUBLE, atan2.type()); - assertTrue(atan2.valueOf(valueEnv()).isMissing()); - - atan2 = DSL.atan2(DSL.literal(1), DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan2.type()); - assertTrue(atan2.valueOf(valueEnv()).isMissing()); - - atan2 = DSL.atan2(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan2.type()); - assertTrue(atan2.valueOf(valueEnv()).isMissing()); - } - - /** - * Test atan2 with missing value. - */ - @Test - public void atan2_null_missing() { - FunctionExpression atan2 = DSL.atan2( - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan2.type()); - assertTrue(atan2.valueOf(valueEnv()).isMissing()); - - atan2 = DSL.atan2(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE), - DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, atan2.type()); - assertTrue(atan2.valueOf(valueEnv()).isMissing()); - } - /** * Test cos with integer, long, float, double values. */ @@ -2415,26 +1801,6 @@ public void test_cos(Number value) { assertEquals(String.format("cos(%s)", value), cos.toString()); } - /** - * Test cos with null value. - */ - @Test - public void cos_null_value() { - FunctionExpression cos = DSL.cos(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, cos.type()); - assertTrue(cos.valueOf(valueEnv()).isNull()); - } - - /** - * Test cos with missing value. - */ - @Test - public void cos_missing_value() { - FunctionExpression cos = DSL.cos(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, cos.type()); - assertTrue(cos.valueOf(valueEnv()).isMissing()); - } - /** * Test cosh with byte value. */ @@ -2526,26 +1892,6 @@ public void cot_with_zero(Number value) { String.format("Out of range value for cot(%s)", value)); } - /** - * Test cot with null value. - */ - @Test - public void cot_null_value() { - FunctionExpression cot = DSL.cot(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, cot.type()); - assertTrue(cot.valueOf(valueEnv()).isNull()); - } - - /** - * Test cot with missing value. - */ - @Test - public void cot_missing_value() { - FunctionExpression cot = DSL.cot(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, cot.type()); - assertTrue(cot.valueOf(valueEnv()).isMissing()); - } - /** * Test degrees with integer, long, float, double values. */ @@ -2559,26 +1905,6 @@ public void test_degrees(Number value) { assertEquals(String.format("degrees(%s)", value), degrees.toString()); } - /** - * Test degrees with null value. - */ - @Test - public void degrees_null_value() { - FunctionExpression degrees = DSL.degrees(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, degrees.type()); - assertTrue(degrees.valueOf(valueEnv()).isNull()); - } - - /** - * Test degrees with missing value. - */ - @Test - public void degrees_missing_value() { - FunctionExpression degrees = DSL.degrees(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, degrees.type()); - assertTrue(degrees.valueOf(valueEnv()).isMissing()); - } - /** * Test radians with integer, long, float, double values. */ @@ -2592,26 +1918,6 @@ public void test_radians(Number value) { assertEquals(String.format("radians(%s)", value), radians.toString()); } - /** - * Test radians with null value. - */ - @Test - public void radians_null_value() { - FunctionExpression radians = DSL.radians(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, radians.type()); - assertTrue(radians.valueOf(valueEnv()).isNull()); - } - - /** - * Test radians with missing value. - */ - @Test - public void radians_missing_value() { - FunctionExpression radians = DSL.radians(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, radians.type()); - assertTrue(radians.valueOf(valueEnv()).isMissing()); - } - /** * Test sin with integer, long, float, double values. */ @@ -2625,26 +1931,6 @@ public void test_sin(Number value) { assertEquals(String.format("sin(%s)", value), sin.toString()); } - /** - * Test sin with null value. - */ - @Test - public void sin_null_value() { - FunctionExpression sin = DSL.sin(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, sin.type()); - assertTrue(sin.valueOf(valueEnv()).isNull()); - } - - /** - * Test sin with missing value. - */ - @Test - public void sin_missing_value() { - FunctionExpression sin = DSL.sin(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, sin.type()); - assertTrue(sin.valueOf(valueEnv()).isMissing()); - } - /** * Test tan with integer, long, float, double values. */ @@ -2658,26 +1944,6 @@ public void test_tan(Number value) { assertEquals(String.format("tan(%s)", value), tan.toString()); } - /** - * Test tan with null value. - */ - @Test - public void tan_null_value() { - FunctionExpression tan = DSL.tan(DSL.ref(DOUBLE_TYPE_NULL_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, tan.type()); - assertTrue(tan.valueOf(valueEnv()).isNull()); - } - - /** - * Test tan with missing value. - */ - @Test - public void tan_missing_value() { - FunctionExpression tan = DSL.tan(DSL.ref(DOUBLE_TYPE_MISSING_VALUE_FIELD, DOUBLE)); - assertEquals(DOUBLE, tan.type()); - assertTrue(tan.valueOf(valueEnv()).isMissing()); - } - /** * Test cbrt with int value. */ @@ -2732,24 +1998,4 @@ public void cbrt_negative_value(Double value) { assertThat(cbrt.valueOf(valueEnv()), allOf(hasType(DOUBLE), hasValue(Math.cbrt(value)))); assertEquals(String.format("cbrt(%s)", value), cbrt.toString()); } - - /** - * Test cbrt with null value. - */ - @Test - public void cbrt_null_value() { - FunctionExpression cbrt = DSL.cbrt(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, cbrt.type()); - assertTrue(cbrt.valueOf(valueEnv()).isNull()); - } - - /** - * Test cbrt with missing value. - */ - @Test - public void cbrt_missing_value() { - FunctionExpression cbrt = DSL.cbrt(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(DOUBLE, cbrt.type()); - assertTrue(cbrt.valueOf(valueEnv()).isMissing()); - } } diff --git a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/UnaryFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/UnaryFunctionTest.java deleted file mode 100644 index e69de29bb2..0000000000 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 4dcfde994f..ad07dbc975 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 @@ -443,45 +443,6 @@ private String getExpectedStringRepr(ExprType widerType, ExprValue value) { return String.format("cast_to_%s(%s)", widerType.toString().toLowerCase(), value); } - @Test - public void test_null_equal_missing() { - FunctionExpression equal = DSL.equal(DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN), - DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, equal.type()); - assertEquals(LITERAL_MISSING, equal.valueOf(valueEnv())); - - equal = DSL.equal(DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN), - DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, equal.type()); - assertEquals(LITERAL_NULL, equal.valueOf(valueEnv())); - - equal = DSL.equal(DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN), - DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, equal.type()); - assertEquals(LITERAL_MISSING, equal.valueOf(valueEnv())); - - equal = DSL.equal(DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN), - DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, equal.type()); - assertEquals(LITERAL_MISSING, equal.valueOf(valueEnv())); - - equal = DSL.equal(DSL.literal(LITERAL_TRUE), DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, equal.type()); - assertEquals(LITERAL_MISSING, equal.valueOf(valueEnv())); - - equal = DSL.equal(DSL.literal(LITERAL_TRUE), DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, equal.type()); - assertEquals(LITERAL_NULL, equal.valueOf(valueEnv())); - - equal = DSL.equal(DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN), DSL.literal(LITERAL_TRUE)); - assertEquals(BOOLEAN, equal.type()); - assertEquals(LITERAL_MISSING, equal.valueOf(valueEnv())); - - equal = DSL.equal(DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN), DSL.literal(LITERAL_TRUE)); - assertEquals(BOOLEAN, equal.type()); - assertEquals(LITERAL_NULL, equal.valueOf(valueEnv())); - } - @ParameterizedTest(name = "equal({0}, {1})") @MethodSource({"testEqualArguments", "testNotEqualArguments"}) public void test_notequal(ExprValue v1, ExprValue v2) { @@ -499,49 +460,6 @@ public void test_notequal(ExprValue v1, ExprValue v2) { assertStringRepr(v1, v2, "!=", notequal); } - @Test - public void test_null_notequal_missing() { - FunctionExpression notequal = DSL.notequal(DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN), - DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, notequal.type()); - assertEquals(LITERAL_MISSING, notequal.valueOf(valueEnv())); - - notequal = DSL.notequal(DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN), - DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, notequal.type()); - assertEquals(LITERAL_NULL, notequal.valueOf(valueEnv())); - - notequal = DSL.notequal(DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN), - DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, notequal.type()); - assertEquals(LITERAL_MISSING, notequal.valueOf(valueEnv())); - - notequal = DSL.notequal(DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN), - DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, notequal.type()); - assertEquals(LITERAL_MISSING, notequal.valueOf(valueEnv())); - - notequal = DSL.notequal(DSL.literal(LITERAL_TRUE), - DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, notequal.type()); - assertEquals(LITERAL_MISSING, notequal.valueOf(valueEnv())); - - notequal = DSL.notequal(DSL.literal(LITERAL_TRUE), - DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN)); - assertEquals(BOOLEAN, notequal.type()); - assertEquals(LITERAL_NULL, notequal.valueOf(valueEnv())); - - notequal = DSL.notequal(DSL.ref(BOOL_TYPE_MISSING_VALUE_FIELD, BOOLEAN), - DSL.literal(LITERAL_TRUE)); - assertEquals(BOOLEAN, notequal.type()); - assertEquals(LITERAL_MISSING, notequal.valueOf(valueEnv())); - - notequal = DSL.notequal(DSL.ref(BOOL_TYPE_NULL_VALUE_FIELD, BOOLEAN), - DSL.literal(LITERAL_TRUE)); - assertEquals(BOOLEAN, notequal.type()); - assertEquals(LITERAL_NULL, notequal.valueOf(valueEnv())); - } - @ParameterizedTest(name = "less({0}, {1})") @MethodSource("testCompareValueArguments") public void test_less(ExprValue v1, ExprValue v2) { @@ -552,53 +470,6 @@ public void test_less(ExprValue v1, ExprValue v2) { assertStringRepr(v1, v2, "<", less); } - @Test - public void test_less_null() { - FunctionExpression less = DSL.less(DSL.literal(1), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, less.type()); - assertEquals(LITERAL_NULL, less.valueOf(valueEnv())); - - less = DSL.less(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(BOOLEAN, less.type()); - assertEquals(LITERAL_NULL, less.valueOf(valueEnv())); - - less = DSL.less(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, less.type()); - assertEquals(LITERAL_NULL, less.valueOf(valueEnv())); - } - - @Test - public void test_less_missing() { - FunctionExpression less = DSL.less(DSL.literal(1), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, less.type()); - assertEquals(LITERAL_MISSING, less.valueOf(valueEnv())); - - less = DSL.less(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(BOOLEAN, less.type()); - assertEquals(LITERAL_MISSING, less.valueOf(valueEnv())); - - less = DSL.less(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, less.type()); - assertEquals(LITERAL_MISSING, less.valueOf(valueEnv())); - } - - @Test - public void test_null_less_missing() { - FunctionExpression less = DSL.less(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, less.type()); - assertEquals(LITERAL_MISSING, less.valueOf(valueEnv())); - - less = DSL.less(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, less.type()); - assertEquals(LITERAL_MISSING, less.valueOf(valueEnv())); - } - @ParameterizedTest(name = "lte({0}, {1})") @MethodSource("testCompareValueArguments") public void test_lte(ExprValue v1, ExprValue v2) { @@ -609,53 +480,6 @@ public void test_lte(ExprValue v1, ExprValue v2) { assertStringRepr(v1, v2, "<=", lte); } - @Test - public void test_lte_null() { - FunctionExpression lte = DSL.lte(DSL.literal(1), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, lte.type()); - assertEquals(LITERAL_NULL, lte.valueOf(valueEnv())); - - lte = DSL.lte(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(BOOLEAN, lte.type()); - assertEquals(LITERAL_NULL, lte.valueOf(valueEnv())); - - lte = DSL.lte(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, lte.type()); - assertEquals(LITERAL_NULL, lte.valueOf(valueEnv())); - } - - @Test - public void test_lte_missing() { - FunctionExpression lte = DSL.lte(DSL.literal(1), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, lte.type()); - assertEquals(LITERAL_MISSING, lte.valueOf(valueEnv())); - - lte = DSL.lte(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(BOOLEAN, lte.type()); - assertEquals(LITERAL_MISSING, lte.valueOf(valueEnv())); - - lte = DSL.lte(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, lte.type()); - assertEquals(LITERAL_MISSING, lte.valueOf(valueEnv())); - } - - @Test - public void test_null_lte_missing() { - FunctionExpression lte = DSL.lte(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, lte.type()); - assertEquals(LITERAL_MISSING, lte.valueOf(valueEnv())); - - lte = DSL.lte(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, lte.type()); - assertEquals(LITERAL_MISSING, lte.valueOf(valueEnv())); - } - @ParameterizedTest(name = "greater({0}, {1})") @MethodSource("testCompareValueArguments") public void test_greater(ExprValue v1, ExprValue v2) { @@ -666,53 +490,6 @@ public void test_greater(ExprValue v1, ExprValue v2) { assertStringRepr(v1, v2, ">", greater); } - @Test - public void test_greater_null() { - FunctionExpression greater = DSL.greater(DSL.literal(1), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, greater.type()); - assertEquals(LITERAL_NULL, greater.valueOf(valueEnv())); - - greater = DSL.greater(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(BOOLEAN, greater.type()); - assertEquals(LITERAL_NULL, greater.valueOf(valueEnv())); - - greater = DSL.greater(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, greater.type()); - assertEquals(LITERAL_NULL, greater.valueOf(valueEnv())); - } - - @Test - public void test_greater_missing() { - FunctionExpression greater = DSL.greater(DSL.literal(1), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, greater.type()); - assertEquals(LITERAL_MISSING, greater.valueOf(valueEnv())); - - greater = DSL.greater(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(BOOLEAN, greater.type()); - assertEquals(LITERAL_MISSING, greater.valueOf(valueEnv())); - - greater = DSL.greater(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, greater.type()); - assertEquals(LITERAL_MISSING, greater.valueOf(valueEnv())); - } - - @Test - public void test_null_greater_missing() { - FunctionExpression greater = DSL.greater(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, greater.type()); - assertEquals(LITERAL_MISSING, greater.valueOf(valueEnv())); - - greater = DSL.greater(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, greater.type()); - assertEquals(LITERAL_MISSING, greater.valueOf(valueEnv())); - } - @ParameterizedTest(name = "gte({0}, {1})") @MethodSource("testCompareValueArguments") public void test_gte(ExprValue v1, ExprValue v2) { @@ -723,53 +500,6 @@ public void test_gte(ExprValue v1, ExprValue v2) { assertStringRepr(v1, v2, ">=", gte); } - @Test - public void test_gte_null() { - FunctionExpression gte = DSL.gte(DSL.literal(1), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, gte.type()); - assertEquals(LITERAL_NULL, gte.valueOf(valueEnv())); - - gte = DSL.gte(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(BOOLEAN, gte.type()); - assertEquals(LITERAL_NULL, gte.valueOf(valueEnv())); - - gte = DSL.gte(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, gte.type()); - assertEquals(LITERAL_NULL, gte.valueOf(valueEnv())); - } - - @Test - public void test_gte_missing() { - FunctionExpression gte = DSL.gte(DSL.literal(1), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, gte.type()); - assertEquals(LITERAL_MISSING, gte.valueOf(valueEnv())); - - gte = DSL.gte(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(BOOLEAN, gte.type()); - assertEquals(LITERAL_MISSING, gte.valueOf(valueEnv())); - - gte = DSL.gte(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, gte.type()); - assertEquals(LITERAL_MISSING, gte.valueOf(valueEnv())); - } - - @Test - public void test_null_gte_missing() { - FunctionExpression gte = DSL.gte(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, gte.type()); - assertEquals(LITERAL_MISSING, gte.valueOf(valueEnv())); - - gte = DSL.gte(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(BOOLEAN, gte.type()); - assertEquals(LITERAL_MISSING, gte.valueOf(valueEnv())); - } - @ParameterizedTest(name = "like({0}, {1})") @MethodSource("testLikeArguments") public void test_like(ExprValue v1, ExprValue v2) { @@ -779,53 +509,6 @@ public void test_like(ExprValue v1, ExprValue v2) { assertEquals(String.format("like(%s, %s)", v1.toString(), v2.toString()), like.toString()); } - @Test - public void test_like_null() { - FunctionExpression like = - DSL.like(DSL.literal("str"), DSL.ref(STRING_TYPE_NULL_VALUE_FIELD, STRING)); - assertEquals(BOOLEAN, like.type()); - assertEquals(LITERAL_NULL, like.valueOf(valueEnv())); - - like = DSL.like(DSL.ref(STRING_TYPE_NULL_VALUE_FIELD, STRING), DSL.literal("str")); - assertEquals(BOOLEAN, like.type()); - assertEquals(LITERAL_NULL, like.valueOf(valueEnv())); - - like = DSL.like(DSL.ref(STRING_TYPE_NULL_VALUE_FIELD, STRING), - DSL.ref(STRING_TYPE_NULL_VALUE_FIELD, STRING)); - assertEquals(BOOLEAN, like.type()); - assertEquals(LITERAL_NULL, like.valueOf(valueEnv())); - } - - @Test - public void test_like_missing() { - FunctionExpression like = - DSL.like(DSL.literal("str"), DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING)); - assertEquals(BOOLEAN, like.type()); - assertEquals(LITERAL_MISSING, like.valueOf(valueEnv())); - - like = DSL.like(DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING), DSL.literal("str")); - assertEquals(BOOLEAN, like.type()); - assertEquals(LITERAL_MISSING, like.valueOf(valueEnv())); - - like = DSL.like(DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING), - DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING)); - assertEquals(BOOLEAN, like.type()); - assertEquals(LITERAL_MISSING, like.valueOf(valueEnv())); - } - - @Test - public void test_null_like_missing() { - FunctionExpression like = DSL.like(DSL.ref(STRING_TYPE_NULL_VALUE_FIELD, STRING), - DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING)); - assertEquals(BOOLEAN, like.type()); - assertEquals(LITERAL_MISSING, like.valueOf(valueEnv())); - - like = DSL.like(DSL.ref(STRING_TYPE_MISSING_VALUE_FIELD, STRING), - DSL.ref(STRING_TYPE_NULL_VALUE_FIELD, STRING)); - assertEquals(BOOLEAN, like.type()); - assertEquals(LITERAL_MISSING, like.valueOf(valueEnv())); - } - @Test public void test_not_like() { FunctionExpression notLike = DSL.notLike(DSL.literal("bob"), DSL.literal("tom")); diff --git a/core/src/test/java/org/opensearch/sql/planner/physical/FilterOperatorTest.java b/core/src/test/java/org/opensearch/sql/planner/physical/FilterOperatorTest.java index f541f6a15f..247cfe6a1d 100644 --- a/core/src/test/java/org/opensearch/sql/planner/physical/FilterOperatorTest.java +++ b/core/src/test/java/org/opensearch/sql/planner/physical/FilterOperatorTest.java @@ -42,7 +42,8 @@ class FilterOperatorTest extends PhysicalPlanTestBase { @Test public void filter_test() { FilterOperator plan = new FilterOperator(new TestScan(), - DSL.equal(DSL.ref("response", INTEGER), DSL.literal(404))); + DSL.and(DSL.notequal(DSL.ref("response", INTEGER), DSL.literal(200)), + DSL.notequal(DSL.ref("response", INTEGER), DSL.literal(500)))); List result = execute(plan); assertEquals(1, result.size()); assertThat(result, containsInAnyOrder(ExprValueUtils diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index d117226c4d..19b724d7d3 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -95,9 +95,19 @@ ABS Description >>>>>>>>>>> -Specifications: +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: same as argument type. -1. ABS(NUMBER T) -> T +Example:: + + os> SELECT ABS(0), ABS(10), ABS(-10), ABS(12.34567), ABS(-12.34567) + fetched rows / total rows = 1/1 + +----------+-----------+------------+-----------------+------------------+ + | ABS(0) | ABS(10) | ABS(-10) | ABS(12.34567) | ABS(-12.34567) | + |----------+-----------+------------+-----------------+------------------| + | 0 | 10 | 10 | 12.34567 | 12.34567 | + +----------+-----------+------------+-----------------+------------------+ ACOS @@ -232,7 +242,7 @@ INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE Example:: - opensearchsql> SELECT CBRT(8), CBRT(9.261), CBRT(-27); + os> SELECT CBRT(8), CBRT(9.261), CBRT(-27); fetched rows / total rows = 1/1 +-----------+---------------+-------------+ | CBRT(8) | CBRT(9.261) | CBRT(-27) | @@ -253,7 +263,11 @@ CEILING Description >>>>>>>>>>> -Usage: CEILING(T) takes the ceiling of value T. +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: INTEGER + +Specifications: Note: `CEIL`_ and CEILING functions have the same implementation & functionality @@ -281,6 +295,16 @@ Example:: | 3147483648 | 113147483648 | 3147483648 | +-----------------------------+-------------------------------+-----------------------------+ +Example:: + + os> SELECT CEIL(0), CEIL(12.34567), CEIL(-12.34567) + fetched rows / total rows = 1/1 + +-----------+------------------+-------------------+ + | CEIL(0) | CEIL(12.34567) | CEIL(-12.34567) | + |-----------+------------------+-------------------| + | 0 | 13 | -12 | + +-----------+------------------+-------------------+ + CONV ---- @@ -304,6 +328,7 @@ Example:: | c | 44 | 1100 | 15 | +----------------------+----------------------+-------------------+---------------------+ + COS --- @@ -471,9 +496,21 @@ EXP Description >>>>>>>>>>> -Specifications: +Usage: EXP() returns Euler's number raised to the specified number. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE -1. EXP(NUMBER T) -> T +Example:: + + os> SELECT EXP(2) + fetched rows / total rows = 1/1 + +------------------+ + | EXP(2) | + |------------------| + | 7.38905609893065 | + +------------------+ EXPM1 @@ -484,6 +521,10 @@ Description Usage: EXPM1(NUMBER T) returns the exponential of T, minus 1. +.. math:: e^{X} - 1 + +See also `EXP`_. + Argument type: INTEGER/LONG/FLOAT/DOUBLE Return type: DOUBLE @@ -498,6 +539,7 @@ Example:: | -0.6321205588285577 | 0.0 | 1.718281828459045 | 3.481689070338065 | +---------------------+------------+-------------------+-------------------+ + FLOOR ----- @@ -538,15 +580,28 @@ Example:: | 282474973688888 | 9223372036854775807 | 9223372036854775807 | +------------------------------+----------------------------------+--------------------------------------+ + LN -- Description >>>>>>>>>>> -Specifications: +Returns the natural logarithm of X; that is, the base-e logarithm of X. If X is NULL or less than or equal to 0, the function returns NULL. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE -1. LN(NUMBER T) -> DOUBLE +Example:: + + os> select LN(1), LN(e()), LN(10), LN(12.34567); + fetched rows / total rows = 1/1 + +---------+-----------+-------------------+--------------------+ + | LN(1) | LN(e()) | LN(10) | LN(12.34567) | + |---------+-----------+-------------------+--------------------| + | 0.0 | 1.0 | 2.302585092994046 | 2.5133053943094317 | + +---------+-----------+-------------------+--------------------+ LOG @@ -555,10 +610,24 @@ LOG Description >>>>>>>>>>> -Specifications: +If called with one parameter, this function returns the natural logarithm of X (see `LN`_). If called with two parameters, this function returns the logarithm of X to the base B. +The inverse of this function (when called with a single argument) is the `EXP`_ function. +If X is NULL or less than or equal to 0, or if B is NULL or less than or equal to 1, then NULL is returned. + +Argument 1 type: INTEGER/LONG/FLOAT/DOUBLE +Argument 2 type (optional): INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: -1. LOG(NUMBER T) -> DOUBLE -2. LOG(NUMBER T, NUMBER) -> DOUBLE + os> select LOG(1), LOG(e()), LOG(2, 65536), LOG(10, 10000); + fetched rows / total rows = 1/1 + +----------+------------+-----------------+------------------+ + | LOG(1) | LOG(e()) | LOG(2, 65536) | LOG(10, 10000) | + |----------+------------+-----------------+------------------| + | 0.0 | 1.0 | 16.0 | 4.0 | + +----------+------------+-----------------+------------------+ LOG2 @@ -567,9 +636,21 @@ LOG2 Description >>>>>>>>>>> -Specifications: +Returns the base-2 logarithm of X. If X is NULL or less than or equal to 0, the function returns NULL. LOG2(X) is useful for finding out how many bits a number requires for storage and equal to LOG(2, X). + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE -1. LOG2(NUMBER T) -> DOUBLE +Example:: + + os> select LOG2(1), LOG2(8), LOG2(65536), LOG2(8.8245); + fetched rows / total rows = 1/1 + +-----------+-----------+---------------+--------------------+ + | LOG2(1) | LOG2(8) | LOG2(65536) | LOG2(8.8245) | + |-----------+-----------+---------------+--------------------| + | 0.0 | 3.0 | 16.0 | 3.1415145369723745 | + +-----------+-----------+---------------+--------------------+ LOG10 @@ -578,9 +659,21 @@ LOG10 Description >>>>>>>>>>> -Specifications: +Returns the base-10 logarithm of X. If X is NULL or less than or equal to 0, the function returns NULL. LOG10(X) is equal to LOG(10, X). + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: -1. LOG10(NUMBER T) -> DOUBLE + os> select LOG10(1), LOG10(8), LOG10(1000), LOG10(8.8245); + fetched rows / total rows = 1/1 + +------------+--------------------+---------------+--------------------+ + | LOG10(1) | LOG10(8) | LOG10(1000) | LOG10(8.8245) | + |------------+--------------------+---------------+--------------------| + | 0.0 | 0.9030899869919435 | 3.0 | 0.9456901074431278 | + +------------+--------------------+---------------+--------------------+ MOD @@ -803,14 +896,12 @@ ROUND Description >>>>>>>>>>> -Usage: ROUND(x, d) rounds the argument x to d decimal places, d defaults to 0 if not specified - -Argument type: INTEGER/LONG/FLOAT/DOUBLE +Usage: ROUND(x, d) rounds the argument x to d decimal places, d defaults to 0 if not specified. -Return type map: +Argument 1 type: INTEGER/LONG/FLOAT/DOUBLE +Argument 2 type (optional): INTEGER -(INTEGER/LONG [,INTEGER]) -> LONG -(FLOAT/DOUBLE [,INTEGER]) -> LONG +Return type: LONG Example:: @@ -885,13 +976,13 @@ Return type: DOUBLE Example:: - os> SELECT SIN(0) + os> select sin(0), sin(1), sin(pi()), abs(sin(pi())) < 0.0001; fetched rows / total rows = 1/1 - +----------+ - | SIN(0) | - |----------| - | 0.0 | - +----------+ + +----------+--------------------+------------------------+---------------------------+ + | sin(0) | sin(1) | sin(pi()) | abs(sin(pi())) < 0.0001 | + |----------+--------------------+------------------------+---------------------------| + | 0.0 | 0.8414709848078965 | 1.2246467991473532e-16 | True | + +----------+--------------------+------------------------+---------------------------+ SINH @@ -966,7 +1057,6 @@ Example:: +----------------------------+----------------------------+ - SUBTRACT -------- @@ -1040,7 +1130,6 @@ Example:: +----------------------+-----------------------+-------------------+ - Date and Time Functions ======================= @@ -1459,6 +1548,7 @@ Example:: | 2008-02-10 02:00:00 | +-----------------------------------------+ + DATE_ADD -------- @@ -1704,6 +1794,7 @@ Example:: | 26 | +----------------------------------+ + DAY_OF_MONTH ------------ @@ -1728,6 +1819,7 @@ Example:: | 26 | +------------------------------+ + DAYOFWEEK --------- @@ -1795,7 +1887,7 @@ Example:: DAY_OF_YEAR ---------- +----------- Description >>>>>>>>>>> @@ -1835,7 +1927,7 @@ Example:: EXTRACT -_______ +------- Description >>>>>>>>>>> @@ -1847,6 +1939,7 @@ Argument type: PART PART must be one of the following tokens in the table below. The format specifiers found in this table are the same as those found in the `DATE_FORMAT`_ function. + .. list-table:: The following table describes the mapping of a 'part' to a particular format. :widths: 20 80 :header-rows: 1 @@ -1904,6 +1997,7 @@ Example:: | 202302 | +--------------------------------------------------+ + FROM_DAYS --------- @@ -2010,6 +2104,27 @@ Example:: | 1 | 1 | +--------------------+---------------------------+ + +LAST_DAY +-------- + +Usage: Returns the last day of the month as a DATE for a valid argument. + +Argument type: DATE/DATETIME/STRING/TIMESTAMP/TIME + +Return type: DATE + +Example:: + + os> SELECT last_day('2023-02-06'); + fetched rows / total rows = 1/1 + +--------------------------+ + | last_day('2023-02-06') | + |--------------------------| + | 2023-02-28 | + +--------------------------+ + + LOCALTIMESTAMP -------------- @@ -2160,8 +2275,9 @@ Example:: | 2 | 2 | +----------------------------+------------------------------------+ + MINUTE_OF_DAY ------- +------------- Description >>>>>>>>>>> @@ -2191,7 +2307,7 @@ Description Usage: month(date) returns the month for date, in the range 1 to 12 for January to December. The dates with value 0 such as '0000-00-00' or '2008-00-00' are invalid. If an argument of type `TIME` is given, the function will use the current date. -The function `month_of_year`_ is also provided as an alias. +The function `month_of_year` is also provided as an alias. Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP @@ -2332,6 +2448,7 @@ Example:: | 3 | +-------------------------------+ + SEC_TO_TIME ----------- @@ -2381,7 +2498,7 @@ Description >>>>>>>>>>> Usage: second(time) returns the second for time, in the range 0 to 59. -The function `second_of_minute`_ is provided as an alias +The function `second_of_minute` is provided as an alias Argument type: STRING/TIME/DATETIME/TIMESTAMP @@ -2704,6 +2821,7 @@ Example:: | 2020-08-26 13:49:00 | 2020-08-27 02:04:42 | +------------------------------------+------------------------------------------------------+ + TIMESTAMPADD ------------ @@ -2727,6 +2845,7 @@ Examples:: | 2000-01-18 00:00:00 | 1999-10-01 00:00:00 | +------------------------------------------------+----------------------------------------------------+ + TIMESTAMPDIFF ------------- @@ -2751,6 +2870,7 @@ Examples:: | 4 | -23 | +---------------------------------------------------------------------+-------------------------------------------------------------+ + TO_DAYS ------- @@ -2773,6 +2893,7 @@ Example:: | 733687 | +------------------------------+ + TO_SECONDS ---------- @@ -2796,6 +2917,7 @@ Example:: | 63390556800 | 62961148800 | +---------------------------------+----------------------+ + UNIX_TIMESTAMP -------------- @@ -2898,6 +3020,7 @@ Example:: | 2022-10-03 17:54:28 | +---------------------+ + WEEK ---- @@ -2963,8 +3086,9 @@ Example:: | 7 | 8 | +----------------------------+-------------------------------+ + WEEKDAY -_______ +------- Description >>>>>>>>>>> @@ -2987,6 +3111,7 @@ Example:: | 2 | 3 | +-------------------------+-------------------------+ + WEEK_OF_YEAR ------------ @@ -3080,6 +3205,7 @@ Example:: | 202034 | 201852 | +--------------------------+-----------------------------+ + String Functions ================ @@ -3151,24 +3277,6 @@ Example:: | hello,world | +------------------------------------+ -LAST_DAY --------- - -Usage: Returns the last day of the month as a DATE for a valid argument. - -Argument type: DATE/DATETIME/STRING/TIMESTAMP/TIME - -Return type: DATE - -Example:: - - os> SELECT last_day('2023-02-06'); - fetched rows / total rows = 1/1 - +--------------------------+ - | last_day('2023-02-06') | - |--------------------------| - | 2023-02-28 | - +--------------------------+ LEFT ---- @@ -3196,10 +3304,6 @@ LENGTH Description >>>>>>>>>>> -Specifications: - -1. LENGTH(STRING) -> INTEGER - Usage: length(str) returns length of string measured in bytes. Argument type: STRING @@ -3290,7 +3394,7 @@ Example:: POSITION ------- +-------- Description >>>>>>>>>>> @@ -3474,19 +3578,10 @@ Example:: | HELLOWORLD | HELLOWORLD | +-----------------------+-----------------------+ -Conditional Functions -===================== -IF --- - -Description ->>>>>>>>>>> - -Specifications: - -1. IF(BOOLEAN, ES_TYPE, ES_TYPE) -> ES_TYPE +Conditional Functions +===================== IFNULL ------ @@ -3494,10 +3589,6 @@ IFNULL Description >>>>>>>>>>> -Specifications: - -1. IFNULL(ES_TYPE, ES_TYPE) -> ES_TYPE - Usage: return parameter2 if parameter1 is null, otherwise return parameter1 Argument type: Any @@ -3541,10 +3632,6 @@ NULLIF Description >>>>>>>>>>> -Specifications: - -1. NULLIF(ES_TYPE, ES_TYPE) -> ES_TYPE - Usage: return null if two parameters are same, otherwise return parameer1 Argument type: Any @@ -3568,10 +3655,6 @@ ISNULL Description >>>>>>>>>>> -Specifications: - -1. ISNULL(ES_TYPE) -> INTEGER - Usage: return true if parameter is null, otherwise return false Argument type: Any @@ -3588,21 +3671,20 @@ Example:: | True | False | +---------------+---------------+ + IF ------- +-- Description >>>>>>>>>>> -Specifications: - -1. IF(condition, ES_TYPE1, ES_TYPE2) -> ES_TYPE1 or ES_TYPE2 - Usage: if first parameter is true, return second parameter, otherwise return third one. Argument type: condition as BOOLEAN, second and third can by any type -Return type: Any (NOTE : if parameters #2 and #3 has different type, you will fail semantic check" +Return type: Any + +NOTE : if parameters #2 and #3 has different type, you will fail semantic check Example:: @@ -3622,6 +3704,7 @@ Example:: | 100 | +-------------------------------+ + CASE ---- @@ -3752,7 +3835,7 @@ Another example to show how to set custom values for the optional parameters:: MATCHQUERY ------ +---------- Description >>>>>>>>>>> @@ -3790,8 +3873,9 @@ Another example to show how to set custom values for the optional parameters:: | Hattie | +-------------+ + MATCH_QUERY ------ +----------- Description >>>>>>>>>>> @@ -3886,8 +3970,9 @@ The match_phrase function also supports an alternative syntax:: | Hattie | +-------------+ + MATCH_BOOL_PREFIX ------ +----------------- Description >>>>>>>>>>> @@ -3927,8 +4012,9 @@ Another example to show how to set custom values for the optional parameters:: | Hattie | 671 Bristol Street | +-------------+--------------------+ + MATCH_PHRASE_PREFIX ------------- +------------------- Description >>>>>>>>>>> @@ -4046,6 +4132,7 @@ The multi_match function also supports an alternative syntax:: | Hattie | +-------------+ + SIMPLE_QUERY_STRING ------------------- @@ -4221,8 +4308,9 @@ Another example to show how to set custom values for the optional parameters:: | 1 | The House at Pooh Corner | Alan Alexander Milne | +------+--------------------------+----------------------+ + SCORE ------------- +----- Description >>>>>>>>>>> @@ -4263,8 +4351,9 @@ Example boosting score:: | 2 | Winnie-the-Pooh | Alan Alexander Milne | 1.1581701 | +------+--------------------------+----------------------+-----------+ + HIGHLIGHT ------------- +--------- Description >>>>>>>>>>> @@ -4288,8 +4377,9 @@ Example searching for field Tags:: | [Winnie-the-Pooh] | +----------------------------------------------+ + WILDCARD_QUERY ------------- +-------------- Description >>>>>>>>>>> @@ -4341,6 +4431,7 @@ Another example to show how to set custom values for the optional parameters:: | tEsT wIlDcArD sensitive cases | +-------------------------------------------+ + NESTED ------ @@ -4364,6 +4455,7 @@ Example with ``field`` and ``path`` parameters:: | b | +---------------------------------+ + System Functions ================ @@ -4389,4 +4481,3 @@ Example:: | DATE | INTEGER | DATETIME | OBJECT | +----------------+---------------+-----------------+------------------+ - diff --git a/docs/user/ppl/functions/datetime.rst b/docs/user/ppl/functions/datetime.rst index 48152de811..904b99a23b 100644 --- a/docs/user/ppl/functions/datetime.rst +++ b/docs/user/ppl/functions/datetime.rst @@ -390,7 +390,6 @@ Example:: +----------------------------+ - DATE_ADD -------- @@ -508,13 +507,13 @@ Return type: STRING Example:: - >od source=people | eval `DATE_FORMAT('1998-01-31 13:14:15.012345', '%T.%f')` = DATE_FORMAT('1998-01-31 13:14:15.012345', '%T.%f'), `DATE_FORMAT(TIMESTAMP('1998-01-31 13:14:15.012345'), '%Y-%b-%D %r')` = DATE_FORMAT(TIMESTAMP('1998-01-31 13:14:15.012345'), '%Y-%b-%D %r') | fields `DATE_FORMAT('1998-01-31 13:14:15.012345', '%T.%f')`, `DATE_FORMAT(TIMESTAMP('1998-01-31 13:14:15.012345'), '%Y-%b-%D %r')` + os> source=people | eval `DATE_FORMAT('1998-01-31 13:14:15.012345', '%T.%f')` = DATE_FORMAT('1998-01-31 13:14:15.012345', '%T.%f'), `DATE_FORMAT(TIMESTAMP('1998-01-31 13:14:15.012345'), '%Y-%b-%D %r')` = DATE_FORMAT(TIMESTAMP('1998-01-31 13:14:15.012345'), '%Y-%b-%D %r') | fields `DATE_FORMAT('1998-01-31 13:14:15.012345', '%T.%f')`, `DATE_FORMAT(TIMESTAMP('1998-01-31 13:14:15.012345'), '%Y-%b-%D %r')` fetched rows / total rows = 1/1 - +-----------------------------------------------+----------------------------------------------------------------+ - | DATE('1998-01-31 13:14:15.012345', '%T.%f') | DATE(TIMESTAMP('1998-01-31 13:14:15.012345'), '%Y-%b-%D %r') | - |-----------------------------------------------+----------------------------------------------------------------| - | '13:14:15.012345' | '1998-Jan-31st 01:14:15 PM' | - +-----------------------------------------------+----------------------------------------------------------------+ + +------------------------------------------------------+-----------------------------------------------------------------------+ + | DATE_FORMAT('1998-01-31 13:14:15.012345', '%T.%f') | DATE_FORMAT(TIMESTAMP('1998-01-31 13:14:15.012345'), '%Y-%b-%D %r') | + |------------------------------------------------------+-----------------------------------------------------------------------| + | 13:14:15.012345 | 1998-Jan-31st 01:14:15 PM | + +------------------------------------------------------+-----------------------------------------------------------------------+ DATETIME @@ -568,6 +567,7 @@ Example:: | null | +---------------------------------------------+ + DATE_SUB -------- @@ -1545,11 +1545,11 @@ Return type: INTEGER Example:: - >od source=people | eval `WEEK(DATE('2008-02-20'))` = WEEK(DATE('2008-02-20')), `WEEK(DATE('2008-02-20'), 1)` = WEEK(DATE('2008-02-20'), 1) | fields `WEEK(DATE('2008-02-20'))`, `WEEK(DATE('2008-02-20'), 1)` + os> source=people | eval `WEEK(DATE('2008-02-20'))` = WEEK(DATE('2008-02-20')), `WEEK(DATE('2008-02-20'), 1)` = WEEK(DATE('2008-02-20'), 1) | fields `WEEK(DATE('2008-02-20'))`, `WEEK(DATE('2008-02-20'), 1)` fetched rows / total rows = 1/1 +----------------------------+-------------------------------+ | WEEK(DATE('2008-02-20')) | WEEK(DATE('2008-02-20'), 1) | - |----------------------------|-------------------------------| + |----------------------------+-------------------------------| | 7 | 8 | +----------------------------+-------------------------------+ diff --git a/docs/user/ppl/functions/math.rst b/docs/user/ppl/functions/math.rst index 9d0b088e80..c5eb07b5da 100644 --- a/docs/user/ppl/functions/math.rst +++ b/docs/user/ppl/functions/math.rst @@ -364,6 +364,7 @@ Example:: | 282474973688888 | 9223372036854775807 | 9223372036854775807 | +------------------------------+----------------------------------+--------------------------------------+ + LN -- @@ -699,6 +700,7 @@ Example:: | 2.0 | 2.1 | +-----------+--------------+ + CBRT ---- diff --git a/docs/user/ppl/functions/relevance.rst b/docs/user/ppl/functions/relevance.rst index 7f7cf50964..8eac6baade 100644 --- a/docs/user/ppl/functions/relevance.rst +++ b/docs/user/ppl/functions/relevance.rst @@ -98,9 +98,8 @@ Another example to show how to set custom values for the optional parameters:: +----------------------+--------------------------+ - MATCH_PHRASE_PREFIX ------------- +------------------- Description >>>>>>>>>>> @@ -140,7 +139,6 @@ Another example to show how to set custom values for the optional parameters:: +----------------------+--------------------------+ - MULTI_MATCH ----------- @@ -247,6 +245,7 @@ Another example to show how to set custom values for the optional parameters:: | 1 | The House at Pooh Corner | Alan Alexander Milne | +------+--------------------------+----------------------+ + MATCH_BOOL_PREFIX ----------------- @@ -288,6 +287,7 @@ Another example to show how to set custom values for the optional parameters:: | Hattie | 671 Bristol Street | +-------------+--------------------+ + QUERY_STRING ------------ @@ -356,4 +356,3 @@ Limitations >>>>>>>>>>> The relevance functions are available to execute only in OpenSearch DSL but not in memory as of now, so the relevance search might fail for queries that are too complex to translate into DSL if the relevance function is following after a complex PPL query. To make your queries always work-able, it is recommended to place the relevance commands as close to the search command as possible, to ensure the relevance functions are eligible to push down. For example, a complex query like ``search source = people | rename firstname as name | dedup account_number | fields name, account_number, balance, employer | where match(employer, 'Open Search') | stats count() by city`` could fail because it is difficult to translate to DSL, but it would be better if we rewrite it to an equivalent query as ``search source = people | where match(employer, 'Open Search') | rename firstname as name | dedup account_number | fields name, account_number, balance, employer | stats count() by city`` by moving the where command with relevance function to the second command right after the search command, and the relevance would be optimized and executed smoothly in OpenSearch DSL. See `Optimization <../../optimization/optimization.rst>`_ to get more details about the query engine optimization. - diff --git a/docs/user/ppl/functions/string.rst b/docs/user/ppl/functions/string.rst index 9b7e69d985..edf5220f4f 100644 --- a/docs/user/ppl/functions/string.rst +++ b/docs/user/ppl/functions/string.rst @@ -82,7 +82,7 @@ Example:: LIKE ------- +---- Description >>>>>>>>>>> @@ -104,6 +104,7 @@ Example:: | True | +---------------------------------+ + LOWER ----- @@ -151,7 +152,7 @@ Example:: POSITION ------- +-------- Description >>>>>>>>>>> @@ -176,7 +177,7 @@ Example:: REVERSE ------ +------- Description >>>>>>>>>>> diff --git a/doctest/build.gradle b/doctest/build.gradle index e2097d4cea..4fa0e6e00f 100644 --- a/doctest/build.gradle +++ b/doctest/build.gradle @@ -144,7 +144,7 @@ testClusters { })) */ plugin ':opensearch-sql-plugin' - testDistribution = 'integ_test' + testDistribution = 'archive' } } tasks.register("runRestTestCluster", RunTask) { diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeFunctionIT.java index b83924bc26..5780dd2d44 100644 --- a/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeFunctionIT.java @@ -6,37 +6,19 @@ package org.opensearch.sql.ppl; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATE; -import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_PEOPLE2; -import static org.opensearch.sql.sql.DateTimeFunctionIT.utcDateTimeNow; 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.MatcherUtils.verifySome; -import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.time.LocalDate; import java.time.LocalTime; -import java.time.Duration; -import java.time.LocalDateTime; -import java.time.Period; -import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.ChronoField; -import java.time.temporal.Temporal; -import java.util.ArrayList; -import java.util.List; import java.util.TimeZone; -import java.util.function.BiFunction; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import org.json.JSONArray; import org.json.JSONObject; import org.junit.After; import org.junit.Before; @@ -828,189 +810,6 @@ public void testMakeDate() throws IOException { verifySome(result.getJSONArray("datarows"), rows("1945-01-06", "1989-06-06")); } - private List> nowLikeFunctionsData() { - return List.of( - ImmutableMap.builder() - .put("name", "now") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "current_timestamp") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "localtimestamp") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "localtime") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "sysdate") - .put("hasFsp", true) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "curtime") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalTime::now) - .put("parser", (BiFunction) LocalTime::parse) - .put("serializationPattern", "HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "current_time") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalTime::now) - .put("parser", (BiFunction) LocalTime::parse) - .put("serializationPattern", "HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "curdate") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalDate::now) - .put("parser", (BiFunction) LocalDate::parse) - .put("serializationPattern", "uuuu-MM-dd") - .build(), - ImmutableMap.builder() - .put("name", "current_date") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalDate::now) - .put("parser", (BiFunction) LocalDate::parse) - .put("serializationPattern", "uuuu-MM-dd") - .build(), - ImmutableMap.builder() - .put("name", "utc_date") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) ()-> utcDateTimeNow().toLocalDate()) - .put("parser", (BiFunction) LocalDate::parse) - .put("serializationPattern", "uuuu-MM-dd") - .build(), - ImmutableMap.builder() - .put("name", "utc_time") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) ()-> utcDateTimeNow().toLocalTime()) - .put("parser", (BiFunction) LocalTime::parse) - .put("serializationPattern", "HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "utc_timestamp") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) ()-> utcDateTimeNow()) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build() - ); - } - - private long getDiff(Temporal sample, Temporal reference) { - if (sample instanceof LocalDate) { - return Period.between((LocalDate) sample, (LocalDate) reference).getDays(); - } - return Duration.between(sample, reference).toSeconds(); - } - - @Test - public void testNowLikeFunctions() throws IOException { - for (var funcData : nowLikeFunctionsData()) { - String name = (String) funcData.get("name"); - Boolean hasFsp = (Boolean) funcData.get("hasFsp"); - Boolean hasShortcut = (Boolean) funcData.get("hasShortcut"); - Boolean constValue = (Boolean) funcData.get("constValue"); - Supplier referenceGetter = (Supplier) funcData.get("referenceGetter"); - BiFunction parser = - (BiFunction) funcData.get("parser"); - String serializationPatternStr = (String) funcData.get("serializationPattern"); - - var serializationPattern = new DateTimeFormatterBuilder() - .appendPattern(serializationPatternStr) - .optionalStart() - .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) - .toFormatter(); - - Temporal reference = referenceGetter.get(); - double delta = 2d; // acceptable time diff, secs - if (reference instanceof LocalDate) - delta = 1d; // Max date delta could be 1 if test runs on the very edge of two days - // We ignore probability of a test run on edge of month or year to simplify the checks - - var calls = new ArrayList() {{ - add(name + "()"); - }}; - if (hasShortcut) - calls.add(name); - if (hasFsp) - calls.add(name + "(0)"); - - // Column order is: func(), func, func(0) - // shortcut ^ fsp ^ - // Query looks like: - // source=people2 | eval `now()`=now() | fields `now()`; - JSONObject result = executeQuery("source=" + TEST_INDEX_PEOPLE2 - + " | eval " + calls.stream().map(c -> String.format("`%s`=%s", c, c)).collect(Collectors.joining(",")) - + " | fields " + calls.stream().map(c -> String.format("`%s`", c)).collect(Collectors.joining(","))); - - var rows = result.getJSONArray("datarows"); - JSONArray firstRow = rows.getJSONArray(0); - for (int i = 0; i < rows.length(); i++) { - var row = rows.getJSONArray(i); - if (constValue) - assertTrue(firstRow.similar(row)); - - int column = 0; - assertEquals(0, - getDiff(reference, parser.apply(row.getString(column++), serializationPattern)), delta); - - if (hasShortcut) { - assertEquals(0, - getDiff(reference, parser.apply(row.getString(column++), serializationPattern)), delta); - } - if (hasFsp) { - assertEquals(0, - getDiff(reference, parser.apply(row.getString(column), serializationPattern)), delta); - } - } - } - } - @Test public void testAddTime() throws IOException { var result = executeQuery(String.format("source=%s | eval" diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/NowLikeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/NowLikeFunctionIT.java new file mode 100644 index 0000000000..a330614d21 --- /dev/null +++ b/integ-test/src/test/java/org/opensearch/sql/ppl/NowLikeFunctionIT.java @@ -0,0 +1,198 @@ +/* + * 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_PEOPLE2; +import static org.opensearch.sql.sql.NowLikeFunctionIT.utcDateTimeNow; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import java.io.IOException; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Period; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.time.temporal.Temporal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.TimeZone; +import java.util.function.BiFunction; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.jupiter.api.Test; + +public class NowLikeFunctionIT extends PPLIntegTestCase { + @Override + public void init() throws Exception { + super.init(); + loadIndex(Index.PEOPLE2); + } + + // Integration test framework sets for OpenSearch instance a random timezone. + // If server's TZ doesn't match localhost's TZ, time measurements for `now` would differ. + // We should set localhost's TZ now and recover the value back in the end of the test. + 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 final String name; + private final Boolean hasFsp; + private final Boolean hasShortcut; + private final Boolean constValue; + private final Supplier referenceGetter; + private final BiFunction parser; + private final String serializationPatternStr; + + public NowLikeFunctionIT( + @Name("name") String name, + @Name("hasFsp") Boolean hasFsp, + @Name("hasShortcut") Boolean hasShortcut, + @Name("constValue") Boolean constValue, + @Name("referenceGetter") Supplier referenceGetter, + @Name("parser") BiFunction parser, + @Name("serializationPatternStr") String serializationPatternStr + ) { + this.name = name; + this.hasFsp = hasFsp; + this.hasShortcut = hasShortcut; + this.constValue = constValue; + this.referenceGetter = referenceGetter; + this.parser = parser; + this.serializationPatternStr = serializationPatternStr; + } + + @ParametersFactory(argumentFormatting = "%1$s") + public static Iterable compareTwoDates() { + return Arrays.asList($$( + $("now", false, false, true, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("current_timestamp", false, false, true, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("localtimestamp", false, false, true, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("localtime", false, false, true, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("sysdate", true, false, false, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("curtime", false, false, false, + (Supplier) LocalTime::now, + (BiFunction) LocalTime::parse, + "HH:mm:ss"), + $("current_time", false, false, false, + (Supplier) LocalTime::now, + (BiFunction) LocalTime::parse, + "HH:mm:ss"), + $("curdate", false, false, false, + (Supplier) LocalDate::now, + (BiFunction) LocalDate::parse, + "uuuu-MM-dd"), + $("current_date", false, false, false, + (Supplier) LocalDate::now, + (BiFunction) LocalDate::parse, + "uuuu-MM-dd"), + $("utc_date", false, false, true, + (Supplier) (() -> utcDateTimeNow().toLocalDate()), + (BiFunction) LocalDate::parse, + "uuuu-MM-dd"), + $("utc_time", false, false, true, + (Supplier) (() -> utcDateTimeNow().toLocalTime()), + (BiFunction) LocalTime::parse, + "HH:mm:ss"), + $("utc_timestamp", false, false, true, + (Supplier) (org.opensearch.sql.sql.NowLikeFunctionIT::utcDateTimeNow), + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss") + )); + } + + private long getDiff(Temporal sample, Temporal reference) { + if (sample instanceof LocalDate) { + return Period.between((LocalDate) sample, (LocalDate) reference).getDays(); + } + return Duration.between(sample, reference).toSeconds(); + } + + @Test + public void testNowLikeFunctions() throws IOException { + var serializationPattern = new DateTimeFormatterBuilder() + .appendPattern(serializationPatternStr) + .optionalStart() + .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) + .toFormatter(); + + Temporal reference = referenceGetter.get(); + double delta = 2d; // acceptable time diff, secs + if (reference instanceof LocalDate) + delta = 1d; // Max date delta could be 1 if test runs on the very edge of two days + // We ignore probability of a test run on edge of month or year to simplify the checks + + var calls = new ArrayList() {{ + add(name + "()"); + }}; + if (hasShortcut) + calls.add(name); + if (hasFsp) + calls.add(name + "(0)"); + + // Column order is: func(), func, func(0) + // shortcut ^ fsp ^ + // Query looks like: + // source=people2 | eval `now()`=now() | fields `now()`; + JSONObject result = executeQuery("source=" + TEST_INDEX_PEOPLE2 + + " | eval " + calls.stream().map(c -> String.format("`%s`=%s", c, c)).collect(Collectors.joining(",")) + + " | fields " + calls.stream().map(c -> String.format("`%s`", c)).collect(Collectors.joining(","))); + + var rows = result.getJSONArray("datarows"); + JSONArray firstRow = rows.getJSONArray(0); + for (int i = 0; i < rows.length(); i++) { + var row = rows.getJSONArray(i); + if (constValue) + assertTrue(firstRow.similar(row)); + + int column = 0; + assertEquals(0, + getDiff(reference, parser.apply(row.getString(column++), serializationPattern)), delta); + + if (hasShortcut) { + assertEquals(0, + getDiff(reference, parser.apply(row.getString(column++), serializationPattern)), delta); + } + if (hasFsp) { + assertEquals(0, + getDiff(reference, parser.apply(row.getString(column), serializationPattern)), delta); + } + } + } +} diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java index b41842f84d..b5677b04a7 100644 --- a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java @@ -8,7 +8,6 @@ import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_CALCS; -import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_PEOPLE2; 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; @@ -17,26 +16,12 @@ import static org.opensearch.sql.util.MatcherUtils.verifySome; import static org.opensearch.sql.util.TestUtils.getResponseBody; -import com.google.common.collect.ImmutableMap; import java.io.IOException; -import java.time.Duration; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.Period; -import java.time.ZoneId; -import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.ChronoField; -import java.time.temporal.Temporal; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; import java.util.TimeZone; -import java.util.function.BiFunction; -import java.util.function.Supplier; -import org.json.JSONArray; import org.json.JSONObject; import org.junit.After; import org.junit.Before; @@ -1167,191 +1152,6 @@ public void testMakeDate() throws IOException { verifyDataRows(result, rows("1945-01-06", "1989-06-06")); } - public static LocalDateTime utcDateTimeNow() { - ZonedDateTime zonedDateTime = - LocalDateTime.now().atZone(TimeZone.getDefault().toZoneId()); - return zonedDateTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); - } - - private List> nowLikeFunctionsData() { - return List.of( - ImmutableMap.builder() - .put("name", "now") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "current_timestamp") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "localtimestamp") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "localtime") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "sysdate") - .put("hasFsp", true) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalDateTime::now) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "curtime") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalTime::now) - .put("parser", (BiFunction) LocalTime::parse) - .put("serializationPattern", "HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "current_time") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalTime::now) - .put("parser", (BiFunction) LocalTime::parse) - .put("serializationPattern", "HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "curdate") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalDate::now) - .put("parser", (BiFunction) LocalDate::parse) - .put("serializationPattern", "uuuu-MM-dd") - .build(), - ImmutableMap.builder() - .put("name", "current_date") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", false) - .put("referenceGetter", (Supplier) LocalDate::now) - .put("parser", (BiFunction) LocalDate::parse) - .put("serializationPattern", "uuuu-MM-dd") - .build(), - ImmutableMap.builder() - .put("name", "utc_date") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) (()-> utcDateTimeNow().toLocalDate())) - .put("parser", (BiFunction) LocalDate::parse) - .put("serializationPattern", "uuuu-MM-dd") - .build(), - ImmutableMap.builder() - .put("name", "utc_time") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) (()-> utcDateTimeNow().toLocalTime())) - .put("parser", (BiFunction) LocalTime::parse) - .put("serializationPattern", "HH:mm:ss") - .build(), - ImmutableMap.builder() - .put("name", "utc_timestamp") - .put("hasFsp", false) - .put("hasShortcut", false) - .put("constValue", true) - .put("referenceGetter", (Supplier) DateTimeFunctionIT::utcDateTimeNow) - .put("parser", (BiFunction) LocalDateTime::parse) - .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") - .build() - ); - } - - private long getDiff(Temporal sample, Temporal reference) { - if (sample instanceof LocalDate) { - return Period.between((LocalDate) sample, (LocalDate) reference).getDays(); - } - return Duration.between(sample, reference).toSeconds(); - } - - @Test - public void testNowLikeFunctions() throws IOException { - for (var funcData : nowLikeFunctionsData()) { - String name = (String) funcData.get("name"); - Boolean hasFsp = (Boolean) funcData.get("hasFsp"); - Boolean hasShortcut = (Boolean) funcData.get("hasShortcut"); - Boolean constValue = (Boolean) funcData.get("constValue"); - Supplier referenceGetter = (Supplier) funcData.get("referenceGetter"); - BiFunction parser = - (BiFunction) funcData.get("parser"); - String serializationPatternStr = (String) funcData.get("serializationPattern"); - - var serializationPattern = new DateTimeFormatterBuilder() - .appendPattern(serializationPatternStr) - .optionalStart() - .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) - .toFormatter(); - - Temporal reference = referenceGetter.get(); - double delta = 2d; // acceptable time diff, secs - if (reference instanceof LocalDate) - delta = 1d; // Max date delta could be 1 if test runs on the very edge of two days - // We ignore probability of a test run on edge of month or year to simplify the checks - - var calls = new ArrayList() {{ - add(name + "()"); - }}; - if (hasShortcut) - calls.add(name); - if (hasFsp) - calls.add(name + "(0)"); - - // Column order is: func(), func, func(0) - // shortcut ^ fsp ^ - JSONObject result = executeQuery("select " + String.join(", ", calls) + " from " + TEST_INDEX_PEOPLE2); - - var rows = result.getJSONArray("datarows"); - JSONArray firstRow = rows.getJSONArray(0); - for (int i = 0; i < rows.length(); i++) { - var row = rows.getJSONArray(i); - if (constValue) - assertTrue(firstRow.similar(row)); - - int column = 0; - assertEquals(0, - getDiff(reference, parser.apply(row.getString(column++), serializationPattern)), delta); - - if (hasShortcut) { - assertEquals(0, - getDiff(reference, parser.apply(row.getString(column++), serializationPattern)), delta); - } - if (hasFsp) { - assertEquals(0, - getDiff(reference, parser.apply(row.getString(column), serializationPattern)), delta); - } - } - } - } - @Test public void testFromUnixTime() throws IOException { var result = executeQuery( diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/NowLikeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/NowLikeFunctionIT.java new file mode 100644 index 0000000000..de3dd0fe98 --- /dev/null +++ b/integ-test/src/test/java/org/opensearch/sql/sql/NowLikeFunctionIT.java @@ -0,0 +1,217 @@ +/* + * 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.TestUtils.getResponseBody; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import java.io.IOException; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Period; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.time.temporal.Temporal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.TimeZone; +import java.util.function.BiFunction; +import java.util.function.Supplier; +import org.json.JSONArray; +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 NowLikeFunctionIT extends SQLIntegTestCase { + @Override + public void init() throws Exception { + super.init(); + } + + // Integration test framework sets for OpenSearch instance a random timezone. + // If server's TZ doesn't match localhost's TZ, time measurements for `now` would differ. + // We should set localhost's TZ now and recover the value back in the end of the test. + 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 final String name; + private final Boolean hasFsp; + private final Boolean hasShortcut; + private final Boolean constValue; + private final Supplier referenceGetter; + private final BiFunction parser; + private final String serializationPatternStr; + + public NowLikeFunctionIT( + @Name("name") String name, + @Name("hasFsp") Boolean hasFsp, + @Name("hasShortcut") Boolean hasShortcut, + @Name("constValue") Boolean constValue, + @Name("referenceGetter") Supplier referenceGetter, + @Name("parser") BiFunction parser, + @Name("serializationPatternStr") String serializationPatternStr + ) { + this.name = name; + this.hasFsp = hasFsp; + this.hasShortcut = hasShortcut; + this.constValue = constValue; + this.referenceGetter = referenceGetter; + this.parser = parser; + this.serializationPatternStr = serializationPatternStr; + } + + @ParametersFactory(argumentFormatting = "%1$s") + public static Iterable compareTwoDates() { + return Arrays.asList($$( + $("now", false, false, true, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("current_timestamp", false, false, true, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("localtimestamp", false, false, true, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("localtime", false, false, true, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("sysdate", true, false, false, + (Supplier) LocalDateTime::now, + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss"), + $("curtime", false, false, false, + (Supplier) LocalTime::now, + (BiFunction) LocalTime::parse, + "HH:mm:ss"), + $("current_time", false, false, false, + (Supplier) LocalTime::now, + (BiFunction) LocalTime::parse, + "HH:mm:ss"), + $("curdate", false, false, false, + (Supplier) LocalDate::now, + (BiFunction) LocalDate::parse, + "uuuu-MM-dd"), + $("current_date", false, false, false, + (Supplier) LocalDate::now, + (BiFunction) LocalDate::parse, + "uuuu-MM-dd"), + $("utc_date", false, false, true, + (Supplier) (() -> utcDateTimeNow().toLocalDate()), + (BiFunction) LocalDate::parse, + "uuuu-MM-dd"), + $("utc_time", false, false, true, + (Supplier) (() -> utcDateTimeNow().toLocalTime()), + (BiFunction) LocalTime::parse, + "HH:mm:ss"), + $("utc_timestamp", false, false, true, + (Supplier) (NowLikeFunctionIT::utcDateTimeNow), + (BiFunction) LocalDateTime::parse, + "uuuu-MM-dd HH:mm:ss") + )); + } + + private long getDiff(Temporal sample, Temporal reference) { + if (sample instanceof LocalDate) { + return Period.between((LocalDate) sample, (LocalDate) reference).getDays(); + } + return Duration.between(sample, reference).toSeconds(); + } + + public static LocalDateTime utcDateTimeNow() { + ZonedDateTime zonedDateTime = + LocalDateTime.now().atZone(TimeZone.getDefault().toZoneId()); + return zonedDateTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); + } + + @Test + public void testNowLikeFunctions() throws IOException { + var serializationPattern = new DateTimeFormatterBuilder() + .appendPattern(serializationPatternStr) + .optionalStart() + .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) + .toFormatter(); + + Temporal reference = referenceGetter.get(); + double delta = 2d; // acceptable time diff, secs + if (reference instanceof LocalDate) + delta = 1d; // Max date delta could be 1 if test runs on the very edge of two days + // We ignore probability of a test run on edge of month or year to simplify the checks + + var calls = new ArrayList() {{ + add(name + "()"); + }}; + if (hasShortcut) + calls.add(name); + if (hasFsp) + calls.add(name + "(0)"); + + // Column order is: func(), func, func(0) + // shortcut ^ fsp ^ + JSONObject result = executeQuery("select " + String.join(", ", calls)); + + var rows = result.getJSONArray("datarows"); + JSONArray firstRow = rows.getJSONArray(0); + for (int i = 0; i < rows.length(); i++) { + var row = rows.getJSONArray(i); + if (constValue) + assertTrue(firstRow.similar(row)); + + int column = 0; + assertEquals(0, + getDiff(reference, parser.apply(row.getString(column++), serializationPattern)), delta); + + if (hasShortcut) { + assertEquals(0, + getDiff(reference, parser.apply(row.getString(column++), serializationPattern)), delta); + } + if (hasFsp) { + assertEquals(0, + getDiff(reference, parser.apply(row.getString(column), serializationPattern)), delta); + } + } + } + + 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)); + } +} diff --git a/opensearch/src/main/java/org/opensearch/sql/opensearch/storage/script/filter/lucene/relevance/RelevanceQuery.java b/opensearch/src/main/java/org/opensearch/sql/opensearch/storage/script/filter/lucene/relevance/RelevanceQuery.java index e07c0cd966..b8641a5c0b 100644 --- a/opensearch/src/main/java/org/opensearch/sql/opensearch/storage/script/filter/lucene/relevance/RelevanceQuery.java +++ b/opensearch/src/main/java/org/opensearch/sql/opensearch/storage/script/filter/lucene/relevance/RelevanceQuery.java @@ -89,10 +89,6 @@ public QueryBuilder build(FunctionExpression func) { protected abstract String getQueryName(); - public Map> getQueryBuildActions() { - return queryBuildActions; - } - /** * Convenience interface for a function that updates a QueryBuilder * based on ExprValue. diff --git a/ppl/src/main/antlr/OpenSearchPPLParser.g4 b/ppl/src/main/antlr/OpenSearchPPLParser.g4 index 80ffffb228..cca99407bb 100644 --- a/ppl/src/main/antlr/OpenSearchPPLParser.g4 +++ b/ppl/src/main/antlr/OpenSearchPPLParser.g4 @@ -33,8 +33,22 @@ pplCommands ; commands - : whereCommand | fieldsCommand | renameCommand | statsCommand | dedupCommand | sortCommand | evalCommand | headCommand - | topCommand | rareCommand | grokCommand | parseCommand | patternsCommand | kmeansCommand | adCommand | mlCommand; + : whereCommand + | fieldsCommand + | renameCommand + | statsCommand + | dedupCommand + | sortCommand + | evalCommand + | headCommand + | topCommand + | rareCommand + | grokCommand + | parseCommand + | patternsCommand + | kmeansCommand + | adCommand + | mlCommand; searchCommand : (SEARCH)? fromClause #searchFrom @@ -220,7 +234,15 @@ statsFunction ; statsFunctionName - : AVG | COUNT | SUM | MIN | MAX | VAR_SAMP | VAR_POP | STDDEV_SAMP | STDDEV_POP + : AVG + | COUNT + | SUM + | MIN + | MAX + | VAR_SAMP + | VAR_POP + | STDDEV_SAMP + | STDDEV_POP ; takeAggFunction @@ -366,11 +388,11 @@ convertedDataType ; evalFunctionName - : mathematicalFunctionBase - | dateAndTimeFunctionBase - | textFunctionBase + : mathematicalFunctionName + | dateTimeFunctionName + | textFunctionName | conditionFunctionBase - | systemFunctionBase + | systemFunctionName | positionFunctionName ; @@ -387,12 +409,38 @@ relevanceArg ; relevanceArgName - : ALLOW_LEADING_WILDCARD | ANALYZER | ANALYZE_WILDCARD | AUTO_GENERATE_SYNONYMS_PHRASE_QUERY - | BOOST | CUTOFF_FREQUENCY | DEFAULT_FIELD | DEFAULT_OPERATOR | ENABLE_POSITION_INCREMENTS - | ESCAPE | FIELDS | FLAGS | FUZZINESS | FUZZY_MAX_EXPANSIONS | FUZZY_PREFIX_LENGTH - | FUZZY_REWRITE | FUZZY_TRANSPOSITIONS | LENIENT | LOW_FREQ_OPERATOR | MAX_DETERMINIZED_STATES - | MAX_EXPANSIONS | MINIMUM_SHOULD_MATCH | OPERATOR | PHRASE_SLOP | PREFIX_LENGTH - | QUOTE_ANALYZER | QUOTE_FIELD_SUFFIX | REWRITE | SLOP | TIE_BREAKER | TIME_ZONE | TYPE + : ALLOW_LEADING_WILDCARD + | ANALYZER + | ANALYZE_WILDCARD + | AUTO_GENERATE_SYNONYMS_PHRASE_QUERY + | BOOST + | CUTOFF_FREQUENCY + | DEFAULT_FIELD + | DEFAULT_OPERATOR + | ENABLE_POSITION_INCREMENTS + | ESCAPE + | FIELDS + | FLAGS + | FUZZINESS + | FUZZY_MAX_EXPANSIONS + | FUZZY_PREFIX_LENGTH + | FUZZY_REWRITE + | FUZZY_TRANSPOSITIONS + | LENIENT + | LOW_FREQ_OPERATOR + | MAX_DETERMINIZED_STATES + | MAX_EXPANSIONS + | MINIMUM_SHOULD_MATCH + | OPERATOR + | PHRASE_SLOP + | PREFIX_LENGTH + | QUOTE_ANALYZER + | QUOTE_FIELD_SUFFIX + | REWRITE + | SLOP + | TIE_BREAKER + | TIME_ZONE + | TYPE | ZERO_TERMS_QUERY ; @@ -421,17 +469,46 @@ relevanceArgValue | literalValue ; -mathematicalFunctionBase - : ABS | CBRT | CEIL | CEILING | CONV | CRC32 | E | EXP | FLOOR | LN | LOG | LOG10 | LOG2 | MOD | PI |POW | POWER - | RAND | ROUND | SIGN | SQRT | TRUNCATE +mathematicalFunctionName + : ABS + | CBRT + | CEIL + | CEILING + | CONV + | CRC32 + | E + | EXP + | FLOOR + | LN + | LOG + | LOG10 + | LOG2 + | MOD + | PI + | POW + | POWER + | RAND + | ROUND + | SIGN + | SQRT + | TRUNCATE | trigonometricFunctionName ; trigonometricFunctionName - : ACOS | ASIN | ATAN | ATAN2 | COS | COT | DEGREES | RADIANS | SIN | TAN - ; - -dateAndTimeFunctionBase + : ACOS + | ASIN + | ATAN + | ATAN2 + | COS + | COT + | DEGREES + | RADIANS + | SIN + | TAN + ; + +dateTimeFunctionName : ADDDATE | ADDTIME | CONVERT_TZ @@ -486,16 +563,35 @@ dateAndTimeFunctionBase /** condition function return boolean value */ conditionFunctionBase : LIKE - | IF | ISNULL | ISNOTNULL | IFNULL | NULLIF + | IF + | ISNULL + | ISNOTNULL + | IFNULL + | NULLIF ; -systemFunctionBase +systemFunctionName : TYPEOF ; -textFunctionBase - : SUBSTR | SUBSTRING | TRIM | LTRIM | RTRIM | LOWER | UPPER | CONCAT | CONCAT_WS | LENGTH | STRCMP - | RIGHT | LEFT | ASCII | LOCATE | REPLACE | REVERSE +textFunctionName + : SUBSTR + | SUBSTRING + | TRIM + | LTRIM + | RTRIM + | LOWER + | UPPER + | CONCAT + | CONCAT_WS + | LENGTH + | STRCMP + | RIGHT + | LEFT + | ASCII + | LOCATE + | REPLACE + | REVERSE ; positionFunctionName @@ -504,10 +600,15 @@ positionFunctionName /** operators */ comparisonOperator - : EQUAL | NOT_EQUAL | LESS | NOT_LESS | GREATER | NOT_GREATER | REGEXP + : EQUAL + | NOT_EQUAL + | LESS + | NOT_LESS + | GREATER + | NOT_GREATER + | REGEXP ; - singleFieldRelevanceFunctionName : MATCH | MATCH_PHRASE @@ -571,14 +672,46 @@ timestampLiteral ; intervalUnit - : MICROSECOND | SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | QUARTER | YEAR | SECOND_MICROSECOND - | MINUTE_MICROSECOND | MINUTE_SECOND | HOUR_MICROSECOND | HOUR_SECOND | HOUR_MINUTE | DAY_MICROSECOND - | DAY_SECOND | DAY_MINUTE | DAY_HOUR | YEAR_MONTH + : MICROSECOND + | SECOND + | MINUTE + | HOUR + | DAY + | WEEK + | MONTH + | QUARTER + | YEAR + | SECOND_MICROSECOND + | MINUTE_MICROSECOND + | MINUTE_SECOND + | HOUR_MICROSECOND + | HOUR_SECOND + | HOUR_MINUTE + | DAY_MICROSECOND + | DAY_SECOND + | DAY_MINUTE + | DAY_HOUR + | YEAR_MONTH ; timespanUnit - : MS | S | M | H | D | W | Q | Y - | MILLISECOND | SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | QUARTER | YEAR + : MS + | S + | M + | H + | D + | W + | Q + | Y + | MILLISECOND + | SECOND + | MINUTE + | HOUR + | DAY + | WEEK + | MONTH + | QUARTER + | YEAR ; @@ -614,6 +747,10 @@ keywordsCanBeId | evalFunctionName | relevanceArgName | intervalUnit + | dateTimeFunctionName + | textFunctionName + | mathematicalFunctionName + | positionFunctionName // commands | SEARCH | DESCRIBE | SHOW | FROM | WHERE | FIELDS | RENAME | STATS | DEDUP | SORT | EVAL | HEAD | TOP | RARE | PARSE | METHOD | REGEX | PUNCT | GROK | PATTERN | PATTERNS | NEW_FIELD | KMEANS | AD | ML diff --git a/sql/src/main/antlr/OpenSearchSQLParser.g4 b/sql/src/main/antlr/OpenSearchSQLParser.g4 index ebc2b8747e..9b7aef6e27 100644 --- a/sql/src/main/antlr/OpenSearchSQLParser.g4 +++ b/sql/src/main/antlr/OpenSearchSQLParser.g4 @@ -189,7 +189,10 @@ constant ; decimalLiteral - : DECIMAL_LITERAL | ZERO_DECIMAL | ONE_DECIMAL | TWO_DECIMAL + : DECIMAL_LITERAL + | ZERO_DECIMAL + | ONE_DECIMAL + | TWO_DECIMAL ; stringLiteral @@ -198,7 +201,8 @@ stringLiteral ; booleanLiteral - : TRUE | FALSE + : TRUE + | FALSE ; realLiteral @@ -206,7 +210,8 @@ realLiteral ; sign - : PLUS | MINUS + : PLUS + | MINUS ; nullLiteral @@ -249,9 +254,26 @@ intervalLiteral ; intervalUnit - : MICROSECOND | SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | QUARTER | YEAR | SECOND_MICROSECOND - | MINUTE_MICROSECOND | MINUTE_SECOND | HOUR_MICROSECOND | HOUR_SECOND | HOUR_MINUTE | DAY_MICROSECOND - | DAY_SECOND | DAY_MINUTE | DAY_HOUR | YEAR_MONTH + : MICROSECOND + | SECOND + | MINUTE + | HOUR + | DAY + | WEEK + | MONTH + | QUARTER + | YEAR + | SECOND_MICROSECOND + | MINUTE_MICROSECOND + | MINUTE_SECOND + | HOUR_MICROSECOND + | HOUR_SECOND + | HOUR_MINUTE + | DAY_MICROSECOND + | DAY_SECOND + | DAY_MINUTE + | DAY_HOUR + | YEAR_MONTH ; // predicates @@ -292,8 +314,13 @@ expressionAtom ; comparisonOperator - : '=' | '>' | '<' | '<' '=' | '>' '=' - | '<' '>' | '!' '=' + : '=' + | '>' + | '<' + | '<' '=' + | '>' '=' + | '<' '>' + | '!' '=' ; nullNotnull @@ -464,22 +491,72 @@ filterClause ; aggregationFunctionName - : AVG | COUNT | SUM | MIN | MAX | VAR_POP | VAR_SAMP | VARIANCE | STD | STDDEV | STDDEV_POP | STDDEV_SAMP + : AVG + | COUNT + | SUM + | MIN + | MAX + | VAR_POP + | VAR_SAMP + | VARIANCE + | STD + | STDDEV + | STDDEV_POP + | STDDEV_SAMP ; mathematicalFunctionName - : ABS | CBRT | CEIL | CEILING | CONV | CRC32 | E | EXP | EXPM1 | FLOOR | LN | LOG | LOG10 | LOG2 | MOD | PI | POW | POWER - | RAND | RINT | ROUND | SIGN | SIGNUM | SQRT | TRUNCATE + : ABS + | CBRT + | CEIL + | CEILING + | CONV + | CRC32 + | E + | EXP + | EXPM1 + | FLOOR + | LN + | LOG + | LOG10 + | LOG2 + | MOD + | PI + | POW + | POWER + | RAND + | RINT + | ROUND + | SIGN + | SIGNUM + | SQRT + | TRUNCATE | trigonometricFunctionName | arithmeticFunctionName ; trigonometricFunctionName - : ACOS | ASIN | ATAN | ATAN2 | COS | COSH | COT | DEGREES | RADIANS | SIN | SINH | TAN + : ACOS + | ASIN + | ATAN + | ATAN2 + | COS + | COSH + | COT + | DEGREES + | RADIANS + | SIN + | SINH + | TAN ; arithmeticFunctionName - : ADD | SUBTRACT | MULTIPLY | DIVIDE | MOD | MODULUS + : ADD + | SUBTRACT + | MULTIPLY + | DIVIDE + | MOD + | MODULUS ; dateTimeFunctionName @@ -545,13 +622,31 @@ dateTimeFunctionName ; textFunctionName - : SUBSTR | SUBSTRING | TRIM | LTRIM | RTRIM | LOWER | UPPER - | CONCAT | CONCAT_WS | SUBSTR | LENGTH | STRCMP | RIGHT | LEFT - | ASCII | LOCATE | REPLACE | REVERSE + : SUBSTR + | SUBSTRING + | TRIM + | LTRIM + | RTRIM + | LOWER + | UPPER + | CONCAT + | CONCAT_WS + | SUBSTR + | LENGTH + | STRCMP + | RIGHT + | LEFT + | ASCII + | LOCATE + | REPLACE + | REVERSE ; flowControlFunctionName - : IF | IFNULL | NULLIF | ISNULL + : IF + | IFNULL + | NULLIF + | ISNULL ; noFieldRelevanceFunctionName @@ -571,10 +666,16 @@ scoreRelevanceFunctionName ; singleFieldRelevanceFunctionName - : MATCH | MATCHQUERY | MATCH_QUERY - | MATCH_PHRASE | MATCHPHRASE | MATCHPHRASEQUERY - | MATCH_BOOL_PREFIX | MATCH_PHRASE_PREFIX - | WILDCARD_QUERY | WILDCARDQUERY + : MATCH + | MATCHQUERY + | MATCH_QUERY + | MATCH_PHRASE + | MATCHPHRASE + | MATCHPHRASEQUERY + | MATCH_BOOL_PREFIX + | MATCH_PHRASE_PREFIX + | WILDCARD_QUERY + | WILDCARDQUERY ; multiFieldRelevanceFunctionName @@ -615,17 +716,45 @@ highlightArg ; relevanceArgName - : ALLOW_LEADING_WILDCARD | ANALYZER | ANALYZE_WILDCARD | AUTO_GENERATE_SYNONYMS_PHRASE_QUERY - | BOOST | CASE_INSENSITIVE | CUTOFF_FREQUENCY | DEFAULT_FIELD | DEFAULT_OPERATOR | ENABLE_POSITION_INCREMENTS - | ESCAPE | FIELDS | FLAGS | FUZZINESS | FUZZY_MAX_EXPANSIONS | FUZZY_PREFIX_LENGTH - | FUZZY_REWRITE | FUZZY_TRANSPOSITIONS | LENIENT | LOW_FREQ_OPERATOR | MAX_DETERMINIZED_STATES - | MAX_EXPANSIONS | MINIMUM_SHOULD_MATCH | OPERATOR | PHRASE_SLOP | PREFIX_LENGTH - | QUOTE_ANALYZER | QUOTE_FIELD_SUFFIX | REWRITE | SLOP | TIE_BREAKER | TIME_ZONE | TYPE + : ALLOW_LEADING_WILDCARD + | ANALYZER + | ANALYZE_WILDCARD + | AUTO_GENERATE_SYNONYMS_PHRASE_QUERY + | BOOST + | CASE_INSENSITIVE + | CUTOFF_FREQUENCY + | DEFAULT_FIELD + | DEFAULT_OPERATOR + | ENABLE_POSITION_INCREMENTS + | ESCAPE + | FIELDS + | FLAGS + | FUZZINESS + | FUZZY_MAX_EXPANSIONS + | FUZZY_PREFIX_LENGTH + | FUZZY_REWRITE + | FUZZY_TRANSPOSITIONS + | LENIENT + | LOW_FREQ_OPERATOR + | MAX_DETERMINIZED_STATES + | MAX_EXPANSIONS + | MINIMUM_SHOULD_MATCH + | OPERATOR + | PHRASE_SLOP + | PREFIX_LENGTH + | QUOTE_ANALYZER + | QUOTE_FIELD_SUFFIX + | REWRITE + | SLOP + | TIE_BREAKER + | TIME_ZONE + | TYPE | ZERO_TERMS_QUERY ; highlightArgName - : HIGHLIGHT_POST_TAGS | HIGHLIGHT_PRE_TAGS + : HIGHLIGHT_POST_TAGS + | HIGHLIGHT_PRE_TAGS ; relevanceFieldAndWeight