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 f665627838..7ec6586060 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 628106b048..c62ece9e43 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 d77a2615d2..4a7218b1a9 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 a7ae605a7f..217e15f3c3 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 @@ -88,12 +84,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/datetime/DateTimeFunction.java b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java index 89a870087e..8a0be28248 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 @@ -31,6 +31,7 @@ import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_LONG_YEAR; import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_SHORT_YEAR; import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_STRICT_WITH_TZ; +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; @@ -111,6 +112,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()); @@ -148,11 +150,10 @@ public void register(BuiltinFunctionRepository repository) { repository.register(time_to_sec()); repository.register(timediff()); repository.register(timestamp()); + repository.register(to_days()); repository.register(utc_date()); repository.register(utc_time()); repository.register(utc_timestamp()); - repository.register(date_format()); - repository.register(to_days()); repository.register(unix_timestamp()); repository.register(week(BuiltinFunctionName.WEEK)); repository.register(week(BuiltinFunctionName.WEEK_OF_YEAR)); @@ -962,7 +963,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) { @@ -1010,7 +1010,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); @@ -1124,7 +1123,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)); } @@ -1439,7 +1438,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 c4b106bbf4..ffca0ce149 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; /** * The definition of arithmetic function @@ -50,160 +52,130 @@ public static void register(BuiltinFunctionRepository repository) { } private static DefaultFunctionResolver add() { - return FunctionDSL.define(BuiltinFunctionName.ADD.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() + v2.byteValue())), + return define(BuiltinFunctionName.ADD.getName(), + 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.addExact(v1.integerValue(), - v2.integerValue()))), + impl(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()))), + impl(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())), + 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) ); } private static DefaultFunctionResolver subtract() { - return FunctionDSL.define(BuiltinFunctionName.SUBTRACT.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() - v2.byteValue())), + return define(BuiltinFunctionName.SUBTRACT.getName(), + 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) ); } private static DefaultFunctionResolver multiply() { - return FunctionDSL.define(BuiltinFunctionName.MULTIPLY.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() * v2.byteValue())), + return define(BuiltinFunctionName.MULTIPLY.getName(), + 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) ); } private static DefaultFunctionResolver divide() { - return FunctionDSL.define(BuiltinFunctionName.DIVIDE.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() / v2.byteValue())), + return define(BuiltinFunctionName.DIVIDE.getName(), + impl(nullMissingHandling( + (v1, v2) -> v2.byteValue() == 0 ? ExprNullValue.of() : + 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) ); } - private static DefaultFunctionResolver modules() { - return FunctionDSL.define(BuiltinFunctionName.MODULES.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprByteValue(v1.byteValue() % v2.byteValue())), + return define(BuiltinFunctionName.MODULES.getName(), + impl(nullMissingHandling( + (v1, v2) -> v2.byteValue() == 0 ? ExprNullValue.of() : + 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) ); } 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 20b7928307..f3e2df61ff 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; @@ -38,7 +41,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; @@ -52,11 +54,18 @@ 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(cot()); repository.register(crc32()); + repository.register(degrees()); repository.register(euler()); repository.register(exp()); repository.register(floor()); @@ -65,24 +74,17 @@ public static void register(BuiltinFunctionRepository repository) { 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(round()); repository.register(sign()); - 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(cot()); - repository.register(degrees()); - repository.register(radians()); repository.register(sin()); + repository.register(sqrt()); repository.register(tan()); + repository.register(truncate()); } /** @@ -90,24 +92,18 @@ public static void register(BuiltinFunctionRepository repository) { * 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) ); } @@ -117,17 +113,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) ); } @@ -140,18 +134,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) ); } @@ -163,14 +153,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) ); } @@ -180,8 +169,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) ); } @@ -190,9 +179,9 @@ private static DefaultFunctionResolver euler() { * of exp function is INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver exp() { - return FunctionDSL.define(BuiltinFunctionName.EXP.getName(), + return define(BuiltinFunctionName.EXP.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.exp(v.doubleValue()))), type, DOUBLE)).collect(Collectors.toList())); } @@ -202,9 +191,8 @@ private static DefaultFunctionResolver exp() { * 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) ); } @@ -214,9 +202,9 @@ private static DefaultFunctionResolver floor() { * ln function is INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver ln() { - return FunctionDSL.define(BuiltinFunctionName.LN.getName(), + return define(BuiltinFunctionName.LN.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.log(v.doubleValue()))), type, DOUBLE)).collect(Collectors.toList())); } @@ -232,21 +220,19 @@ 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 -> new ExprDoubleValue(Math.log(v.doubleValue()))), + builder.add(impl(nullMissingHandling(v -> 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) -> new ExprDoubleValue( + builder.add(impl(nullMissingHandling((b, x) -> 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()); } @@ -255,9 +241,9 @@ private static DefaultFunctionResolver log() { * log function is SHORT/INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver log10() { - return FunctionDSL.define(BuiltinFunctionName.LOG10.getName(), + return define(BuiltinFunctionName.LOG10.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.log10(v.doubleValue()))), type, DOUBLE)).collect(Collectors.toList())); } @@ -267,9 +253,9 @@ private static DefaultFunctionResolver log10() { * function is SHORT/INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver log2() { - return FunctionDSL.define(BuiltinFunctionName.LOG2.getName(), + return define(BuiltinFunctionName.LOG2.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.log(v.doubleValue()) / Math.log(2))), DOUBLE, type)) .collect(Collectors.toList())); } @@ -282,37 +268,24 @@ private static DefaultFunctionResolver log2() { * -> wider type between types of x and y */ private static DefaultFunctionResolver mod() { - return FunctionDSL.define(BuiltinFunctionName.MOD.getName(), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.byteValue() == 0 ? ExprNullValue.of() : - new ExprByteValue(v1.byteValue() % v2.byteValue())), + return define(BuiltinFunctionName.MOD.getName(), + impl(nullMissingHandling((v1, v2) -> v2.byteValue() == 0 ? ExprNullValue.of() : + 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.shortValue() == 0 ? ExprNullValue.of() : - new ExprIntegerValue(Math.floorMod(v1.integerValue(), - v2.integerValue()))), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprIntegerValue(Math.floorMod(v1.integerValue(), v2.integerValue()))), INTEGER, INTEGER, INTEGER), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : - new ExprLongValue(Math.floorMod(v1.longValue(), v2.longValue()))), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprLongValue(Math.floorMod(v1.longValue(), v2.longValue()))), LONG, LONG, LONG), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : - new ExprFloatValue(v1.floatValue() % v2.floatValue())), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprFloatValue(v1.floatValue() % v2.floatValue())), FLOAT, FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : - new ExprDoubleValue(v1.doubleValue() % v2.doubleValue())), + impl(nullMissingHandling((v1, v2) -> v2.shortValue() == 0 ? ExprNullValue.of() : + new ExprDoubleValue(v1.doubleValue() % v2.doubleValue())), DOUBLE, DOUBLE, DOUBLE) ); } @@ -323,8 +296,8 @@ private static DefaultFunctionResolver mod() { * () -> 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) ); } @@ -338,35 +311,30 @@ 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) -> new ExprDoubleValue(Math.pow(v1.floatValue(), v2.floatValue()))), + impl(nullMissingHandling( + (v1, v2) -> new ExprDoubleValue(Math.pow(v1.floatValue(), v2.floatValue()))), DOUBLE, FLOAT, FLOAT), - FunctionDSL.impl( - FunctionDSL.nullMissingHandling( - (v1, v2) -> new ExprDoubleValue(Math.pow(v1.doubleValue(), v2.doubleValue()))), + impl(nullMissingHandling( + (v1, v2) -> new ExprDoubleValue(Math.pow(v1.doubleValue(), v2.doubleValue()))), DOUBLE, DOUBLE, DOUBLE)); } @@ -380,11 +348,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) ); } @@ -398,47 +365,30 @@ private static DefaultFunctionResolver rand() { * (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)); } @@ -450,9 +400,9 @@ private static DefaultFunctionResolver round() { * SHORT/INTEGER/LONG/FLOAT/DOUBLE -> INTEGER */ private static DefaultFunctionResolver sign() { - return FunctionDSL.define(BuiltinFunctionName.SIGN.getName(), + return define(BuiltinFunctionName.SIGN.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprIntegerValue(Math.signum(v.doubleValue()))), INTEGER, type)).collect(Collectors.toList())); } @@ -464,9 +414,9 @@ private static DefaultFunctionResolver sign() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver sqrt() { - return FunctionDSL.define(BuiltinFunctionName.SQRT.getName(), + return define(BuiltinFunctionName.SQRT.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> v.doubleValue() < 0 ? ExprNullValue.of() : new ExprDoubleValue(Math.sqrt(v.doubleValue()))), DOUBLE, type)).collect(Collectors.toList())); @@ -479,9 +429,9 @@ private static DefaultFunctionResolver sqrt() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver cbrt() { - return FunctionDSL.define(BuiltinFunctionName.CBRT.getName(), + return define(BuiltinFunctionName.CBRT.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.cbrt(v.doubleValue()))), DOUBLE, type)).collect(Collectors.toList())); } @@ -496,30 +446,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)); } @@ -531,9 +469,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())); @@ -547,9 +485,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())); @@ -568,15 +506,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()); } /** @@ -591,12 +528,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()); } /** @@ -606,9 +542,9 @@ private static DefaultFunctionResolver atan2() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver cos() { - return FunctionDSL.define(BuiltinFunctionName.COS.getName(), + return define(BuiltinFunctionName.COS.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.cos(v.doubleValue()))), DOUBLE, type)).collect(Collectors.toList())); } @@ -620,9 +556,9 @@ private static DefaultFunctionResolver cos() { * 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) { @@ -641,9 +577,9 @@ private static DefaultFunctionResolver cot() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver degrees() { - return FunctionDSL.define(BuiltinFunctionName.DEGREES.getName(), + return define(BuiltinFunctionName.DEGREES.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.toDegrees(v.doubleValue()))), type, DOUBLE)).collect(Collectors.toList())); } @@ -655,9 +591,9 @@ private static DefaultFunctionResolver degrees() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver radians() { - return FunctionDSL.define(BuiltinFunctionName.RADIANS.getName(), + return define(BuiltinFunctionName.RADIANS.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.toRadians(v.doubleValue()))), DOUBLE, type)).collect(Collectors.toList())); } @@ -669,9 +605,9 @@ private static DefaultFunctionResolver radians() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver sin() { - return FunctionDSL.define(BuiltinFunctionName.SIN.getName(), + return define(BuiltinFunctionName.SIN.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.sin(v.doubleValue()))), DOUBLE, type)).collect(Collectors.toList())); } @@ -683,9 +619,9 @@ private static DefaultFunctionResolver sin() { * INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE */ private static DefaultFunctionResolver tan() { - return FunctionDSL.define(BuiltinFunctionName.TAN.getName(), + return define(BuiltinFunctionName.TAN.getName(), ExprCoreType.numberTypes().stream() - .map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling( + .map(type -> impl(nullMissingHandling( v -> new ExprDoubleValue(Math.tan(v.doubleValue()))), DOUBLE, type)).collect(Collectors.toList())); } 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 2556aed8d8..6120e49530 100644 --- a/core/src/main/java/org/opensearch/sql/utils/DateTimeFormatters.java +++ b/core/src/main/java/org/opensearch/sql/utils/DateTimeFormatters.java @@ -29,6 +29,9 @@ @UtilityClass public class DateTimeFormatters { + 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") @@ -108,9 +111,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") @@ -165,9 +165,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 ff9f154f75..1f6f11709f 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,17 +10,12 @@ 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.INTERVAL; import static org.opensearch.sql.data.type.ExprCoreType.LONG; import static org.opensearch.sql.data.type.ExprCoreType.STRING; import static org.opensearch.sql.data.type.ExprCoreType.TIME; @@ -31,13 +26,11 @@ 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; @@ -45,33 +38,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; -@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", @@ -170,76 +145,45 @@ FunctionExpression getDateFormatExpression() { public void adddate() { FunctionExpression expr = DSL.adddate(DSL.date(DSL.literal("2020-08-26")), DSL.literal(7)); assertEquals(DATE, expr.type()); - assertEquals(new ExprDateValue("2020-09-02"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-09-02"), expr.valueOf()); assertEquals("adddate(date(\"2020-08-26\"), 7)", expr.toString()); expr = DSL.adddate(DSL.timestamp(DSL.literal("2020-08-26 12:05:00")), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-09-02 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-09-02 12:05:00"), expr.valueOf()); assertEquals("adddate(timestamp(\"2020-08-26 12:05:00\"), 7)", expr.toString()); expr = DSL.adddate( DSL.date(DSL.literal("2020-08-26")), DSL.interval(DSL.literal(1), DSL.literal("hour"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-26 01:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-26 01:00:00"), expr.valueOf()); assertEquals("adddate(date(\"2020-08-26\"), interval(1, \"hour\"))", expr.toString()); expr = DSL.adddate(DSL.literal("2020-08-26"), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDateValue("2020-09-02"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-09-02"), expr.valueOf()); assertEquals("adddate(\"2020-08-26\", 7)", expr.toString()); expr = DSL.adddate(DSL.literal("2020-08-26 12:05:00"), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-09-02 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-09-02 12:05:00"), expr.valueOf()); assertEquals("adddate(\"2020-08-26 12:05:00\", 7)", expr.toString()); expr = DSL .adddate(DSL.literal("2020-08-26"), DSL.interval(DSL.literal(1), DSL.literal("hour"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-26 01:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-26 01:00:00"), expr.valueOf()); assertEquals("adddate(\"2020-08-26\", interval(1, \"hour\"))", expr.toString()); expr = DSL .adddate(DSL.literal("2020-08-26"), DSL.interval(DSL.literal(1), DSL.literal("day"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDateValue("2020-08-27"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-08-27"), expr.valueOf()); assertEquals("adddate(\"2020-08-26\", interval(1, \"day\"))", expr.toString()); - - when(nullRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.adddate(nullRef, DSL.literal(1L)))); - assertEquals(nullValue(), - eval(DSL.adddate(nullRef, DSL.interval(DSL.literal(1), DSL.literal("month"))))); - - when(missingRef.type()).thenReturn(DATE); - assertEquals(missingValue(), eval(DSL.adddate(missingRef, DSL.literal(1L)))); - assertEquals(missingValue(), - eval(DSL.adddate(missingRef, DSL.interval(DSL.literal(1), DSL.literal("month"))))); - - when(nullRef.type()).thenReturn(LONG); - when(missingRef.type()).thenReturn(LONG); - assertEquals(nullValue(), eval(DSL.adddate(DSL.date(DSL.literal("2020-08-26")), nullRef))); - assertEquals(missingValue(), - eval(DSL.adddate(DSL.date(DSL.literal("2020-08-26")), missingRef))); - - when(nullRef.type()).thenReturn(INTERVAL); - when(missingRef.type()).thenReturn(INTERVAL); - assertEquals(nullValue(), eval(DSL.adddate(DSL.date(DSL.literal("2020-08-26")), nullRef))); - assertEquals(missingValue(), - eval(DSL.adddate(DSL.date(DSL.literal("2020-08-26")), missingRef))); - - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(INTERVAL); - assertEquals(missingValue(), eval(DSL.adddate(nullRef, missingRef))); } @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)); @@ -259,136 +203,77 @@ 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 date_add() { FunctionExpression expr = DSL.date_add(DSL.date(DSL.literal("2020-08-26")), DSL.literal(7)); assertEquals(DATE, expr.type()); - assertEquals(new ExprDateValue("2020-09-02"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-09-02"), expr.valueOf()); assertEquals("date_add(date(\"2020-08-26\"), 7)", expr.toString()); expr = DSL.date_add(DSL.literal("2020-08-26 12:05:00"), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-09-02 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-09-02 12:05:00"), expr.valueOf()); assertEquals("date_add(\"2020-08-26 12:05:00\", 7)", expr.toString()); expr = DSL.date_add(DSL.timestamp(DSL.literal("2020-08-26 12:05:00")), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-09-02 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-09-02 12:05:00"), expr.valueOf()); assertEquals("date_add(timestamp(\"2020-08-26 12:05:00\"), 7)", expr.toString()); expr = DSL.date_add( DSL.date(DSL.literal("2020-08-26")), DSL.interval(DSL.literal(1), DSL.literal("hour"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-26 01:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-26 01:00:00"), expr.valueOf()); assertEquals("date_add(date(\"2020-08-26\"), interval(1, \"hour\"))", expr.toString()); expr = DSL .date_add(DSL.literal("2020-08-26"), DSL.interval(DSL.literal(1), DSL.literal("hour"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-26 01:00:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-26 01:00:00"), expr.valueOf()); assertEquals("date_add(\"2020-08-26\", interval(1, \"hour\"))", expr.toString()); - - when(nullRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.date_add(nullRef, DSL.literal(1L)))); - assertEquals(nullValue(), - eval(DSL.date_add(nullRef, DSL.interval(DSL.literal(1), DSL.literal("month"))))); - - when(missingRef.type()).thenReturn(DATE); - assertEquals(missingValue(), eval(DSL.date_add(missingRef, DSL.literal(1L)))); - assertEquals(missingValue(), - eval(DSL.date_add(missingRef, DSL.interval(DSL.literal(1), DSL.literal("month"))))); - - when(nullRef.type()).thenReturn(LONG); - when(missingRef.type()).thenReturn(LONG); - assertEquals(nullValue(), eval(DSL.date_add(DSL.date(DSL.literal("2020-08-26")), nullRef))); - assertEquals(missingValue(), - eval(DSL.date_add(DSL.date(DSL.literal("2020-08-26")), missingRef))); - - when(nullRef.type()).thenReturn(INTERVAL); - when(missingRef.type()).thenReturn(INTERVAL); - assertEquals(nullValue(), eval(DSL.date_add(DSL.date(DSL.literal("2020-08-26")), nullRef))); - assertEquals(missingValue(), - eval(DSL.date_add(DSL.date(DSL.literal("2020-08-26")), missingRef))); - - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(INTERVAL); - assertEquals(missingValue(), eval(DSL.date_add(nullRef, missingRef))); } @Test public void date_sub() { FunctionExpression expr = DSL.date_sub(DSL.date(DSL.literal("2020-08-26")), DSL.literal(7)); assertEquals(DATE, expr.type()); - assertEquals(new ExprDateValue("2020-08-19"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-08-19"), expr.valueOf()); assertEquals("date_sub(date(\"2020-08-26\"), 7)", expr.toString()); expr = DSL.date_sub(DSL.literal("2020-08-26"), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDateValue("2020-08-19"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-08-19"), expr.valueOf()); assertEquals("date_sub(\"2020-08-26\", 7)", expr.toString()); expr = DSL.date_sub(DSL.timestamp(DSL.literal("2020-08-26 12:05:00")), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-19 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-19 12:05:00"), expr.valueOf()); assertEquals("date_sub(timestamp(\"2020-08-26 12:05:00\"), 7)", expr.toString()); expr = DSL.date_sub(DSL.literal("2020-08-26 12:05:00"), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-19 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-19 12:05:00"), expr.valueOf()); assertEquals("date_sub(\"2020-08-26 12:05:00\", 7)", expr.toString()); expr = DSL.date_sub(DSL.timestamp(DSL.literal("2020-08-26 12:05:00")), DSL.interval(DSL.literal(1), DSL.literal("hour"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-26 11:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-26 11:05:00"), expr.valueOf()); assertEquals("date_sub(timestamp(\"2020-08-26 12:05:00\"), interval(1, \"hour\"))", expr.toString()); expr = DSL.date_sub(DSL.literal("2020-08-26 12:05:00"), DSL.interval(DSL.literal(1), DSL.literal("year"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2019-08-26 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2019-08-26 12:05:00"), expr.valueOf()); assertEquals("date_sub(\"2020-08-26 12:05:00\", interval(1, \"year\"))", expr.toString()); - - when(nullRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.date_sub(nullRef, DSL.literal(1L)))); - assertEquals(nullValue(), - eval(DSL.date_sub(nullRef, DSL.interval(DSL.literal(1), DSL.literal("month"))))); - - when(missingRef.type()).thenReturn(DATE); - assertEquals(missingValue(), eval(DSL.date_sub(missingRef, DSL.literal(1L)))); - assertEquals(missingValue(), - eval(DSL.date_sub(missingRef, DSL.interval(DSL.literal(1), DSL.literal("month"))))); - - when(nullRef.type()).thenReturn(LONG); - when(missingRef.type()).thenReturn(LONG); - assertEquals(nullValue(), eval(DSL.date_sub(DSL.date(DSL.literal("2020-08-26")), nullRef))); - assertEquals(missingValue(), - eval(DSL.date_sub(DSL.date(DSL.literal("2020-08-26")), missingRef))); - - when(nullRef.type()).thenReturn(INTERVAL); - when(missingRef.type()).thenReturn(INTERVAL); - assertEquals(nullValue(), eval(DSL.date_sub(DSL.date(DSL.literal("2020-08-26")), nullRef))); - assertEquals(missingValue(), - eval(DSL.date_sub(DSL.date(DSL.literal("2020-08-26")), missingRef))); - - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(INTERVAL); - assertEquals(missingValue(), eval(DSL.date_sub(nullRef, missingRef))); } @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()); @@ -402,11 +287,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()); @@ -420,11 +300,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()); @@ -444,10 +319,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")); @@ -458,14 +329,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"))); @@ -484,9 +352,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); @@ -497,14 +362,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")), @@ -528,9 +386,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"))); @@ -566,9 +421,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"))); @@ -596,8 +448,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"))); @@ -619,9 +469,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( @@ -643,11 +490,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, @@ -665,11 +507,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()); @@ -717,9 +554,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, @@ -729,9 +563,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')", @@ -750,9 +581,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"))); @@ -777,9 +605,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), @@ -792,9 +617,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), @@ -824,13 +646,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, @@ -850,24 +666,14 @@ 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()); } @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)); @@ -880,17 +686,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()); } @@ -901,9 +707,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, @@ -932,9 +735,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( @@ -968,12 +768,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 @@ -990,11 +785,6 @@ public void hourOfDayInvalidArguments() { @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()); @@ -1013,32 +803,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)); @@ -1051,17 +836,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()); } @@ -1073,11 +858,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)); @@ -1090,17 +870,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); @@ -1143,9 +923,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); } @@ -1156,13 +933,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, @@ -1188,11 +959,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()); @@ -1237,9 +1003,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, @@ -1249,9 +1012,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')", @@ -1267,31 +1027,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"))); @@ -1316,11 +1061,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()); @@ -1339,11 +1079,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()); @@ -1362,11 +1097,6 @@ public void quarter() { @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)); @@ -1384,12 +1114,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()); } @@ -1429,9 +1159,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); } @@ -1442,12 +1169,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")), @@ -1468,79 +1190,48 @@ public void secondOfMinuteInvalidArguments() { public void subdate() { FunctionExpression expr = DSL.subdate(DSL.date(DSL.literal("2020-08-26")), DSL.literal(7)); assertEquals(DATE, expr.type()); - assertEquals(new ExprDateValue("2020-08-19"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-08-19"), expr.valueOf()); assertEquals("subdate(date(\"2020-08-26\"), 7)", expr.toString()); expr = DSL.subdate(DSL.literal("2020-08-26"), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDateValue("2020-08-19"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-08-19"), expr.valueOf()); assertEquals("subdate(\"2020-08-26\", 7)", expr.toString()); expr = DSL.subdate(DSL.timestamp(DSL.literal("2020-08-26 12:05:00")), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-19 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-19 12:05:00"), expr.valueOf()); assertEquals("subdate(timestamp(\"2020-08-26 12:05:00\"), 7)", expr.toString()); expr = DSL.subdate(DSL.literal("2020-08-26 12:05:00"), DSL.literal(7)); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-19 12:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-19 12:05:00"), expr.valueOf()); assertEquals("subdate(\"2020-08-26 12:05:00\", 7)", expr.toString()); expr = DSL.subdate(DSL.timestamp(DSL.literal("2020-08-26 12:05:00")), DSL.interval(DSL.literal(1), DSL.literal("hour"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-26 11:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-26 11:05:00"), expr.valueOf()); assertEquals("subdate(timestamp(\"2020-08-26 12:05:00\"), interval(1, \"hour\"))", expr.toString()); expr = DSL.subdate(DSL.literal("2020-08-26 12:05:00"), DSL.interval(DSL.literal(1), DSL.literal("hour"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDatetimeValue("2020-08-26 11:05:00"), expr.valueOf(env)); + assertEquals(new ExprDatetimeValue("2020-08-26 11:05:00"), expr.valueOf()); assertEquals("subdate(\"2020-08-26 12:05:00\", interval(1, \"hour\"))", expr.toString()); expr = DSL.subdate(DSL.literal("2020-08-26"), DSL.interval(DSL.literal(1), DSL.literal("day"))); assertEquals(DATETIME, expr.type()); - assertEquals(new ExprDateValue("2020-08-25"), expr.valueOf(env)); + assertEquals(new ExprDateValue("2020-08-25"), expr.valueOf()); assertEquals("subdate(\"2020-08-26\", interval(1, \"day\"))", expr.toString()); - - when(nullRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.subdate(nullRef, DSL.literal(1L)))); - assertEquals(nullValue(), - eval(DSL.subdate(nullRef, DSL.interval(DSL.literal(1), DSL.literal("month"))))); - - when(missingRef.type()).thenReturn(DATE); - assertEquals(missingValue(), eval(DSL.subdate(missingRef, DSL.literal(1L)))); - assertEquals(missingValue(), - eval(DSL.subdate(missingRef, DSL.interval(DSL.literal(1), DSL.literal("month"))))); - - when(nullRef.type()).thenReturn(LONG); - when(missingRef.type()).thenReturn(LONG); - assertEquals(nullValue(), eval(DSL.subdate(DSL.date(DSL.literal("2020-08-26")), nullRef))); - assertEquals(missingValue(), - eval(DSL.subdate(DSL.date(DSL.literal("2020-08-26")), missingRef))); - - when(nullRef.type()).thenReturn(INTERVAL); - when(missingRef.type()).thenReturn(INTERVAL); - assertEquals(nullValue(), eval(DSL.subdate(DSL.date(DSL.literal("2020-08-26")), nullRef))); - assertEquals(missingValue(), - eval(DSL.subdate(DSL.date(DSL.literal("2020-08-26")), missingRef))); - - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(INTERVAL); - assertEquals(missingValue(), eval(DSL.subdate(nullRef, missingRef))); } @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()); @@ -1554,11 +1245,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)); @@ -1596,19 +1282,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(\"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()); } @@ -1630,36 +1311,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( @@ -1699,8 +1350,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); } @@ -1744,8 +1393,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); @@ -1756,9 +1403,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( @@ -1777,8 +1421,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 = @@ -1793,39 +1435,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 invalid month () -> assertThrows( @@ -1844,8 +1455,6 @@ public void testInvalidWeekOfYear() { @Test public void weekOfYearModeInUnsupportedFormat() { - nullMissingWeekOfYearQuery(DATE); - FunctionExpression expression1 = DSL .week_of_year( functionProperties, @@ -1866,11 +1475,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()); @@ -1889,11 +1493,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()); @@ -1922,28 +1521,6 @@ public void date_format() { FunctionExpression expr = DSL.date_format(DSL.literal(timestamp), 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(nullRef, DSL.literal("")))); - assertEquals(missingValue(), eval(DSL.date_format(missingRef, DSL.literal("")))); - - when(nullRef.type()).thenReturn(DATETIME); - when(missingRef.type()).thenReturn(DATETIME); - assertEquals(nullValue(), eval(DSL.date_format(nullRef, DSL.literal("")))); - assertEquals(missingValue(), eval(DSL.date_format(missingRef, DSL.literal("")))); - - when(nullRef.type()).thenReturn(TIMESTAMP); - when(missingRef.type()).thenReturn(TIMESTAMP); - assertEquals(nullValue(), eval(DSL.date_format(nullRef, DSL.literal("")))); - assertEquals(missingValue(), eval(DSL.date_format(missingRef, DSL.literal("")))); - - when(nullRef.type()).thenReturn(STRING); - when(missingRef.type()).thenReturn(STRING); - assertEquals(nullValue(), eval(DSL.date_format(nullRef, DSL.literal("")))); - assertEquals(missingValue(), eval(DSL.date_format(missingRef, DSL.literal("")))); - assertEquals(nullValue(), eval(DSL.date_format(DSL.literal(""), nullRef))); - assertEquals(missingValue(), eval(DSL.date_format(DSL.literal(""), missingRef))); } void testDateFormat(DateFormatTester dft) { @@ -1953,6 +1530,6 @@ void testDateFormat(DateFormatTester dft) { } 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 d8829ea41a..118c668b84 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 @@ -6,7 +6,6 @@ package org.opensearch.sql.expression.datetime; import static org.opensearch.sql.data.model.ExprValueUtils.fromObjectValue; -import static org.opensearch.sql.data.type.ExprCoreType.DOUBLE; import java.time.Instant; import java.time.LocalDate; @@ -16,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; @@ -33,34 +30,28 @@ 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(); } 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 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) { @@ -68,16 +59,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) { @@ -95,10 +83,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) { @@ -107,18 +93,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)); } @@ -139,30 +123,28 @@ protected Integer period_diff(Integer first, Integer second) { } 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() { @@ -170,9 +152,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)); } 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/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 7c0c6f8a82..c766f939c9 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 @@ -8,20 +8,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; 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.data.type.ExprCoreType.SHORT; +import static org.opensearch.sql.data.type.ExprCoreType.BYTE; 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; @@ -40,7 +32,6 @@ import org.opensearch.sql.data.type.ExprType; import org.opensearch.sql.data.type.WideningTypeRule; 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; @@ -76,71 +67,6 @@ public void add(ExprValue op1, ExprValue op2) { assertEquals(String.format("+(%s, %s)", op1.toString(), op2.toString()), expression.toString()); } - @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 = "subtract({1}, {2})") @MethodSource("arithmeticFunctionArguments") public void subtract(ExprValue op1, ExprValue op2) { @@ -175,8 +101,8 @@ public void divide(ExprValue op1, ExprValue op2) { assertEquals(String.format("/(%s, %s)", op1.toString(), op2.toString()), expression.toString()); - expression = DSL.divide(literal(op1), literal(new ExprShortValue(0))); - expectedType = WideningTypeRule.max(op1.type(), SHORT); + expression = DSL.divide(literal(op1), literal(new ExprByteValue(0))); + expectedType = WideningTypeRule.max(op1.type(), BYTE); assertEquals(expectedType, expression.type()); assertTrue(expression.valueOf(valueEnv()).isNull()); assertEquals(String.format("/(%s, 0)", op1.toString()), expression.toString()); @@ -192,8 +118,8 @@ public void module(ExprValue op1, ExprValue op2) { assertEquals(String.format("%%(%s, %s)", op1.toString(), op2.toString()), expression.toString()); - expression = DSL.module(literal(op1), literal(new ExprShortValue(0))); - expectedType = WideningTypeRule.max(op1.type(), SHORT); + expression = DSL.module(literal(op1), literal(new ExprByteValue(0))); + expectedType = WideningTypeRule.max(op1.type(), BYTE); assertEquals(expectedType, expression.type()); assertTrue(expression.valueOf(valueEnv()).isNull()); assertEquals(String.format("%%(%s, 0)", op1.toString()), expression.toString()); 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 3a03ba79ad..22041604b5 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; @@ -171,17 +165,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. */ @@ -268,34 +251,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. */ @@ -396,59 +351,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. */ @@ -464,26 +366,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. */ @@ -545,26 +427,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 floor with integer value. */ @@ -617,26 +479,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. */ @@ -689,26 +531,6 @@ public void ln_double_value(Double value) { assertEquals(String.format("ln(%s)", value.toString()), ln.toString()); } - /** - * 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. */ @@ -769,28 +591,6 @@ public void log_double_value(Double v) { assertEquals(String.format("log(%s)", v.toString()), log.toString()); } - /** - * 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. */ @@ -847,66 +647,6 @@ public void log_two_double_value(Double v1, Double v2) { assertEquals(String.format("log(%s, %s)", v1.toString(), v2.toString()), log.toString()); } - /** - * 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. */ @@ -967,28 +707,6 @@ public void log10_double_value(Double v) { assertEquals(String.format("log10(%s)", v.toString()), log.toString()); } - /** - * 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. */ @@ -1049,28 +767,6 @@ public void log2_double_value(Double v) { assertEquals(String.format("log2(%s)", v.toString()), log.toString()); } - /** - * Test log2 with null 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()); - } - - /** - * Test log2 with missing 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()); - } - /** * Test mod with byte value. */ @@ -1176,62 +872,6 @@ public void mod_double_value(Double v1, Double v2) { assertTrue(mod.valueOf(valueEnv()).isNull()); } - /** - * Test mod with null value. - */ - @Test - public void mod_null_value() { - FunctionExpression mod = DSL.mod(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(INTEGER, mod.type()); - assertTrue(mod.valueOf(valueEnv()).isNull()); - - mod = DSL.mod(DSL.literal(1), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(INTEGER, mod.type()); - assertTrue(mod.valueOf(valueEnv()).isNull()); - - mod = DSL.mod( - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(INTEGER, mod.type()); - assertTrue(mod.valueOf(valueEnv()).isNull()); - } - - /** - * Test mod with missing value. - */ - @Test - public void mod_missing_value() { - FunctionExpression mod = - DSL.mod(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), DSL.literal(1)); - assertEquals(INTEGER, mod.type()); - assertTrue(mod.valueOf(valueEnv()).isMissing()); - - mod = DSL.mod(DSL.literal(1), DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(INTEGER, mod.type()); - assertTrue(mod.valueOf(valueEnv()).isMissing()); - - mod = DSL.mod( - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(INTEGER, mod.type()); - assertTrue(mod.valueOf(valueEnv()).isMissing()); - } - - /** - * Test mod with null and missing values. - */ - @Test - public void mod_null_missing() { - FunctionExpression mod = DSL.mod(DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER)); - assertEquals(INTEGER, mod.type()); - assertTrue(mod.valueOf(valueEnv()).isMissing()); - - mod = DSL.mod(DSL.ref(INT_TYPE_NULL_VALUE_FIELD, INTEGER), - DSL.ref(INT_TYPE_MISSING_VALUE_FIELD, INTEGER)); - assertEquals(INTEGER, mod.type()); - assertTrue(mod.valueOf(valueEnv()).isMissing()); - } - /** * Test pow/power with short value. */ @@ -1328,103 +968,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 round with integer value. */ @@ -1533,60 +1076,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. */ @@ -1639,26 +1128,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 sqrt with int value. */ @@ -1714,26 +1183,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. */ @@ -1789,63 +1238,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. */ @@ -1883,13 +1275,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. */ @@ -1914,26 +1299,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. */ @@ -1958,26 +1323,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. */ @@ -2005,69 +1350,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. */ @@ -2081,63 +1363,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. */ @@ -2151,26 +1376,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 cot with integer, long, float, double values. */ @@ -2196,26 +1401,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. */ @@ -2229,26 +1414,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. */ @@ -2262,26 +1427,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. */ @@ -2295,26 +1440,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. */ @@ -2328,26 +1453,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. */ @@ -2402,24 +1507,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 7354b52e24..8719d2a8a0 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 @@ -384,45 +384,6 @@ public void test_equal(ExprValue v1, ExprValue v2) { assertEquals(String.format("=(%s, %s)", v1.toString(), v2.toString()), equal.toString()); } - @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) { @@ -433,49 +394,6 @@ public void test_notequal(ExprValue v1, ExprValue v2) { assertEquals(String.format("!=(%s, %s)", v1.toString(), v2.toString()), notequal.toString()); } - @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) { @@ -486,53 +404,6 @@ public void test_less(ExprValue v1, ExprValue v2) { assertEquals(String.format("<(%s, %s)", v1.toString(), v2.toString()), less.toString()); } - @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) { @@ -543,53 +414,6 @@ public void test_lte(ExprValue v1, ExprValue v2) { assertEquals(String.format("<=(%s, %s)", v1.toString(), v2.toString()), lte.toString()); } - @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) { @@ -600,53 +424,6 @@ public void test_greater(ExprValue v1, ExprValue v2) { assertEquals(String.format(">(%s, %s)", v1.toString(), v2.toString()), greater.toString()); } - @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) { @@ -657,53 +434,6 @@ public void test_gte(ExprValue v1, ExprValue v2) { assertEquals(String.format(">=(%s, %s)", v1.toString(), v2.toString()), gte.toString()); } - @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) { @@ -713,53 +443,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/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index f433845bb3..c0e79392d5 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 -1. ABS(NUMBER T) -> T +Return type: same as argument type. + +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 @@ -129,9 +139,25 @@ ADD Description >>>>>>>>>>> -Specifications: +`add(a, b)` is equal to `a + b`. -1. ADD(NUMBER T, NUMBER) -> T +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type map: + +(INTEGER/LONG, INTEGER/LONG) -> LONG +(FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE) -> DOUBLE +(INTEGER/LONG/FLOAT/DOUBLE, FLOAT/DOUBLE) -> DOUBLE + +Example:: + + os> select add(2, 3), add(3, 2), add(pi(), e()) from people; + fetched rows / total rows = 1/1 + +-------------+-------------+-------------------+ + | add(2, 3) | add(3, 2) | add(pi(), e()) | + |-------------+-------------+-------------------| + | 5 | 5 | 5.859874482048838 | + +-------------+-------------+-------------------+ ASIN @@ -219,7 +245,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) | @@ -240,7 +266,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 @@ -268,6 +298,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 ---- @@ -291,6 +331,7 @@ Example:: | c | 44 | 1100 | 15 | +----------------------+----------------------+-------------------+---------------------+ + COS --- @@ -320,9 +361,21 @@ COSH Description >>>>>>>>>>> -Specifications: +Returns the hyperbolic cosine of a value. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE -1. COSH(NUMBER T) -> DOUBLE +Return type: DOUBLE + +Example:: + + os> select cosh(0), cosh(1), cosh(pi()) from people; + fetched rows / total rows = 1/1 + +-----------+-------------------+--------------------+ + | cosh(0) | cosh(1) | cosh(pi()) | + |-----------+-------------------+--------------------| + | 1 | 1.543080634815244 | 11.591953275521519 | + +-----------+-------------------+--------------------+ COT @@ -400,9 +453,25 @@ DIVIDE Description >>>>>>>>>>> -Specifications: +`divide(a, b)` is equal to `a / b`. -1. DIVIDE(NUMBER T, NUMBER) -> T +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type map: + +(INTEGER/LONG, INTEGER/LONG) -> LONG +(FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE) -> DOUBLE +(INTEGER/LONG/FLOAT/DOUBLE, FLOAT/DOUBLE) -> DOUBLE + +Example:: + + os> select divide(2, 3), divide(3, 2), divide(3.0, 2), divide(pi(), e()) from people; + fetched rows / total rows = 1/1 + +----------------+----------------+------------------+---------------------+ + | divide(2, 3) | divide(3, 2) | divide(3.0, 2) | divide(pi(), e()) | + |----------------+----------------+------------------+---------------------| + | 0 | 1 | 1.5 | 1.1557273497909217 | + +----------------+----------------+------------------+---------------------+ E @@ -432,9 +501,21 @@ EXP Description >>>>>>>>>>> -Specifications: +Usage: EXP() returns Euler's number raised to the specified number. -1. EXP(NUMBER T) -> T +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: + + os> SELECT EXP(2) + fetched rows / total rows = 1/1 + +------------------+ + | EXP(2) | + |------------------| + | 7.38905609893065 | + +------------------+ EXPM1 @@ -443,9 +524,25 @@ EXPM1 Description >>>>>>>>>>> -Specifications: +EXPM1(X) return Euler's number raised to the specified number minus one according to the formula: -1. EXPM1(NUMBER T) -> T +.. math:: e^{X} - 1 + +See also `EXP`_. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: + + os> select expm1(1) + 1 as `e()`, expm1(0) from people; + fetched rows / total rows = 1/1 + +-------------------+------------+ + | e() | expm1(0) | + |-------------------+------------| + | 2.718281828459045 | 0 | + +-------------------+------------+ FLOOR @@ -488,15 +585,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. -1. LN(NUMBER T) -> DOUBLE +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: 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 @@ -505,10 +615,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. -1. LOG(NUMBER T) -> DOUBLE -2. LOG(NUMBER T, NUMBER) -> DOUBLE +Argument 1 type: INTEGER/LONG/FLOAT/DOUBLE +Argument 2 type (optional): INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: + + 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 @@ -517,9 +641,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 -1. LOG2(NUMBER T) -> DOUBLE +Return type: 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 @@ -528,9 +664,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). -1. LOG10(NUMBER T) -> DOUBLE +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: + + 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 @@ -539,11 +687,17 @@ MOD Description >>>>>>>>>>> -Usage: MOD(n, m) calculates the remainder of the number n divided by m. +Usage: MOD(n, m) calculates the remainder of the number n divided by m. If m equals to 0, then returns NULL. Argument type: INTEGER/LONG/FLOAT/DOUBLE -Return type: Wider type between types of n and m if m is nonzero value. If m equals to 0, then returns NULL. +Return type map: + +(INTEGER/LONG, INTEGER/LONG) -> LONG +(FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE) -> DOUBLE +(INTEGER/LONG/FLOAT/DOUBLE, FLOAT/DOUBLE) -> DOUBLE + +Alias: `modulus` Example:: @@ -562,9 +716,26 @@ MULTIPLY Description >>>>>>>>>>> -Specifications: +MULTIPLY(a, b) calculates multiplication of `a` and `b`. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type map: + +(INTEGER/LONG, INTEGER/LONG) -> LONG +(FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE) -> DOUBLE +(INTEGER/LONG/FLOAT/DOUBLE, FLOAT/DOUBLE) -> DOUBLE + +Example:: + + os> select multiply(2, 3), multiply(2.2, 3.3) from people; + fetched rows / total rows = 1/1 + +------------------+----------------------+ + | multiply(2, 3) | multiply(2.2, 3.3) | + |------------------+----------------------| + | 6 | 7.26 | + +------------------+----------------------+ -1. MULTIPLY(NUMBER T, NUMBER) -> NUMBER PI -- @@ -689,9 +860,24 @@ RINT Description >>>>>>>>>>> -Specifications: +Returns the DOUBLE value that is closest in value to the argument and is equal to a mathematical integer. If two DOUBLE values that are mathematical integers are equally close, the result is the integer value that is even. +Special cases: +* If the argument value is already equal to a mathematical integer, then the result is the same as the argument. +* If the argument is NaN or an infinity or positive zero or negative zero, then the result is the same as the argument. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: -1. RINT(NUMBER T) -> T + os> select rint(2.49), rint(2.51) from people; + fetched rows / total rows = 1/1 + +--------------+--------------+ + | rint(2.49) | rint(2.51) | + |--------------+--------------| + | 2 | 3 | + +--------------+--------------+ ROUND @@ -700,14 +886,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:: @@ -746,12 +930,7 @@ Example:: SIGNUM ------ -Description ->>>>>>>>>>> - -Specifications: - -1. SIGNUM(NUMBER T) -> T +Alias to `SIGN`_. SIN @@ -768,13 +947,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 @@ -783,9 +962,21 @@ SINH Description >>>>>>>>>>> -Specifications: +Returns the hyperbolic sine of a value. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: -1. SINH(NUMBER T) -> DOUBLE + os> select sinh(0), sinh(1), sinh(pi()) from people; + fetched rows / total rows = 1/1 + +-----------+--------------------+--------------------+ + | sinh(0) | sinh(1) | sinh(pi()) | + |-----------+--------------------+--------------------| + | 0 | 1.1752011936438014 | 11.548739357257748 | + +-----------+--------------------+--------------------+ SQRT @@ -837,16 +1028,31 @@ Example:: +----------------------------+----------------------------+ - SUBTRACT -------- Description >>>>>>>>>>> -Specifications: +`subtract(a, b)` is equal to `a - b`. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type map: + +(INTEGER/LONG, INTEGER/LONG) -> LONG +(FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE) -> DOUBLE +(INTEGER/LONG/FLOAT/DOUBLE, FLOAT/DOUBLE) -> DOUBLE -1. SUBTRACT(NUMBER T, NUMBER) -> T +Example:: + + os> select subtract(2, 3), subtract(pi(), e()) from people; + fetched rows / total rows = 1/1 + +------------------+-----------------------+ + | subtract(2, 3) | subtract(pi(), e()) | + |------------------+-----------------------| + | -1 | 0.423310825130748 | + +------------------+-----------------------+ TAN @@ -897,7 +1103,6 @@ Example:: +----------------------+-----------------------+-------------------+ - Date and Time Functions ======================= @@ -1313,6 +1518,7 @@ Example:: | 2008-02-10 02:00:00 | +-----------------------------------------+ + DATE_ADD -------- @@ -1565,6 +1771,7 @@ Example:: | 26 | +----------------------------------+ + DAY_OF_MONTH ------------ @@ -1589,6 +1796,7 @@ Example:: | 26 | +------------------------------+ + DAYOFWEEK --------- @@ -1656,7 +1864,7 @@ Example:: DAY_OF_YEAR ---------- +----------- Description >>>>>>>>>>> @@ -1695,7 +1903,6 @@ Example:: +-------------------------------------------------+ - FROM_DAYS --------- @@ -1779,6 +1986,7 @@ Example:: | 1 | 1 | +--------------------+---------------------------+ + LOCALTIMESTAMP -------------- @@ -1929,8 +2137,9 @@ Example:: | 2 | 2 | +----------------------------+------------------------------------+ + MINUTE_OF_DAY ------- +------------- Description >>>>>>>>>>> @@ -1960,7 +2169,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 @@ -2109,7 +2318,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 @@ -2470,6 +2679,7 @@ Example:: | 2022-10-03 17:54:28 | +---------------------+ + WEEK ---- @@ -2535,8 +2745,9 @@ Example:: | 7 | 8 | +----------------------------+-------------------------------+ + WEEK_OF_YEAR ----- +------------ Description >>>>>>>>>>> @@ -2680,10 +2891,6 @@ LENGTH Description >>>>>>>>>>> -Specifications: - -1. LENGTH(STRING) -> INTEGER - Usage: length(str) returns length of string measured in bytes. Argument type: STRING @@ -2774,7 +2981,7 @@ Example:: POSITION ------- +-------- Description >>>>>>>>>>> @@ -2958,19 +3165,10 @@ Example:: | HELLOWORLD | HELLOWORLD | +-----------------------+-----------------------+ -Conditional Functions -===================== - -IF --- -Description ->>>>>>>>>>> - -Specifications: - -1. IF(BOOLEAN, ES_TYPE, ES_TYPE) -> ES_TYPE +Conditional Functions +===================== IFNULL ------ @@ -2978,10 +3176,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 @@ -3025,10 +3219,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 @@ -3052,10 +3242,6 @@ ISNULL Description >>>>>>>>>>> -Specifications: - -1. ISNULL(ES_TYPE) -> INTEGER - Usage: return true if parameter is null, otherwise return false Argument type: Any @@ -3072,21 +3258,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:: @@ -3106,6 +3291,7 @@ Example:: | 100 | +-------------------------------+ + CASE ---- @@ -3236,7 +3422,7 @@ Another example to show how to set custom values for the optional parameters:: MATCHQUERY ------ +---------- Description >>>>>>>>>>> @@ -3274,8 +3460,9 @@ Another example to show how to set custom values for the optional parameters:: | Hattie | +-------------+ + MATCH_QUERY ------ +----------- Description >>>>>>>>>>> @@ -3370,8 +3557,9 @@ The match_phrase function also supports an alternative syntax:: | Hattie | +-------------+ + MATCH_BOOL_PREFIX ------ +----------------- Description >>>>>>>>>>> @@ -3411,8 +3599,9 @@ Another example to show how to set custom values for the optional parameters:: | Hattie | 671 Bristol Street | +-------------+--------------------+ + MATCH_PHRASE_PREFIX ------------- +------------------- Description >>>>>>>>>>> @@ -3530,6 +3719,7 @@ The multi_match function also supports an alternative syntax:: | Hattie | +-------------+ + SIMPLE_QUERY_STRING ------------------- @@ -3705,8 +3895,9 @@ Another example to show how to set custom values for the optional parameters:: | 1 | The House at Pooh Corner | Alan Alexander Milne | +------+--------------------------+----------------------+ + HIGHLIGHT ------------- +--------- Description >>>>>>>>>>> @@ -3730,8 +3921,9 @@ Example searching for field Tags:: | [Winnie-the-Pooh] | +----------------------------------------------+ + WILDCARD_QUERY ------------- +-------------- Description >>>>>>>>>>> @@ -3783,6 +3975,7 @@ Another example to show how to set custom values for the optional parameters:: | tEsT wIlDcArD sensitive cases | +-------------------------------------------+ + System Functions ================ @@ -3808,4 +4001,3 @@ Example:: | DATE | INTEGER | DATETIME | STRUCT | +----------------+---------------+-----------------+------------------+ - diff --git a/docs/user/ppl/functions/datetime.rst b/docs/user/ppl/functions/datetime.rst index 5e54d8e80f..3bfc5deddb 100644 --- a/docs/user/ppl/functions/datetime.rst +++ b/docs/user/ppl/functions/datetime.rst @@ -386,7 +386,6 @@ Example:: +----------------------------+ - DATE_ADD -------- @@ -507,13 +506,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.12345 | 1998-Jan-31st 01:14:15 PM | + +------------------------------------------------------+-----------------------------------------------------------------------+ @@ -568,6 +567,7 @@ Example:: | null | +---------------------------------------------+ + DATE_SUB -------- @@ -1541,11 +1541,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 20bd1d6a70..199170514f 100644 --- a/docs/user/ppl/functions/math.rst +++ b/docs/user/ppl/functions/math.rst @@ -187,6 +187,7 @@ Example:: | c | 44 | 1100 | 15 | +----------------------+----------------------+-------------------+---------------------+ + COS --- @@ -278,6 +279,7 @@ Example:: | 89.95437383553924 | +-------------------+ + E - @@ -362,6 +364,7 @@ Example:: | 282474973688888 | 9223372036854775807 | 9223372036854775807 | +------------------------------+----------------------------------+--------------------------------------+ + LN -- @@ -697,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 0503759cbd..fbb2aa63c1 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 ec403f32a3..5b0d255d8e 100644 --- a/doctest/build.gradle +++ b/doctest/build.gradle @@ -139,7 +139,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 23f2df69c8..51278796b6 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,34 +6,13 @@ 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_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.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.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.jupiter.api.Test; import org.opensearch.sql.common.utils.StringUtils; @@ -675,196 +654,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 { - // 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. - var testTz = TimeZone.getDefault(); - TimeZone.setDefault(TimeZone.getTimeZone(System.getProperty("user.timezone"))); - - 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); - } - } - } - TimeZone.setDefault(testTz); - } - @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 af8748deab..fd8407b253 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,8 @@ 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.jupiter.api.Test; import org.opensearch.client.Request; @@ -893,198 +874,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 { - // 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. - var testTz = TimeZone.getDefault(); - TimeZone.setDefault(TimeZone.getTimeZone(System.getProperty("user.timezone"))); - - 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); - } - } - } - TimeZone.setDefault(testTz); - } - @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/executor/protector/ResourceMonitorPlan.java b/opensearch/src/main/java/org/opensearch/sql/opensearch/executor/protector/ResourceMonitorPlan.java index 9c59e4acaf..8fc7480dd1 100644 --- a/opensearch/src/main/java/org/opensearch/sql/opensearch/executor/protector/ResourceMonitorPlan.java +++ b/opensearch/src/main/java/org/opensearch/sql/opensearch/executor/protector/ResourceMonitorPlan.java @@ -20,7 +20,7 @@ */ @ToString @RequiredArgsConstructor -@EqualsAndHashCode +@EqualsAndHashCode(callSuper = false) public class ResourceMonitorPlan extends PhysicalPlan { /** 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 dbb63ef12a..c6e7911a12 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,8 +747,8 @@ keywordsCanBeId | TIMESTAMP | DATE | TIME | FIRST | LAST | timespanUnit | SPAN - | dateAndTimeFunctionBase - | textFunctionBase - | mathematicalFunctionBase + | dateTimeFunctionName + | textFunctionName + | mathematicalFunctionName | positionFunctionName ; diff --git a/sql/src/main/antlr/OpenSearchSQLParser.g4 b/sql/src/main/antlr/OpenSearchSQLParser.g4 index 3fa223c584..e85ff77db9 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 @@ -402,17 +429,57 @@ 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 | FLOOR | LN | LOG | LOG10 | LOG2 | MOD | PI | POW | POWER - | RAND | ROUND | SIGN | SQRT | TRUNCATE + : 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 + : ACOS + | ASIN + | ATAN + | ATAN2 + | COS + | COT + | DEGREES + | RADIANS + | SIN + | TAN ; dateTimeFunctionName @@ -470,13 +537,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 @@ -488,10 +573,16 @@ systemFunctionName ; 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 @@ -532,17 +623,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