[Fix](from_unixtime) Keep consistent with MySQL & bug fix (#25966)
Bug fix: implicit convert from int32 -> int64 makes negative time stamp valid, so change signature to int64 Consistent: keep consistent with mysql.
This commit is contained in:
@ -20,12 +20,15 @@ package org.apache.doris.nereids.trees.expressions.functions.executable;
|
||||
import org.apache.doris.nereids.exceptions.AnalysisException;
|
||||
import org.apache.doris.nereids.trees.expressions.ExecFunction;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
|
||||
import org.apache.doris.nereids.types.VarcharType;
|
||||
import org.apache.doris.nereids.util.DateUtils;
|
||||
|
||||
import java.time.Duration;
|
||||
@ -446,22 +449,21 @@ public class DateTimeExtractAndTransform {
|
||||
/**
|
||||
* date transformation function: from_unixtime
|
||||
*/
|
||||
@ExecFunction(name = "from_unixtime", argTypes = {"INT"}, returnType = "VARCHAR")
|
||||
public static Expression fromUnixTime(IntegerLiteral second) {
|
||||
if (second.getValue() < 0 || second.getValue() >= 253402271999L) {
|
||||
return null;
|
||||
}
|
||||
@ExecFunction(name = "from_unixtime", argTypes = {"BIGINT"}, returnType = "VARCHAR")
|
||||
public static Expression fromUnixTime(BigIntLiteral second) {
|
||||
return fromUnixTime(second, new VarcharLiteral("%Y-%m-%d %H:%i:%s"));
|
||||
}
|
||||
|
||||
/**
|
||||
* date transformation function: from_unixtime
|
||||
*/
|
||||
@ExecFunction(name = "from_unixtime", argTypes = {"INT", "VARCHAR"}, returnType = "VARCHAR")
|
||||
public static Expression fromUnixTime(IntegerLiteral second, VarcharLiteral format) {
|
||||
if (second.getValue() < 0) {
|
||||
return null;
|
||||
@ExecFunction(name = "from_unixtime", argTypes = {"BIGINT", "VARCHAR"}, returnType = "VARCHAR")
|
||||
public static Expression fromUnixTime(BigIntLiteral second, VarcharLiteral format) {
|
||||
// 32536771199L is max valid timestamp of mysql from_unix_time
|
||||
if (second.getValue() < 0 || second.getValue() > 32536771199L) {
|
||||
return new NullLiteral(VarcharType.SYSTEM_DEFAULT);
|
||||
}
|
||||
|
||||
ZonedDateTime dateTime = LocalDateTime.of(1970, 1, 1, 0, 0, 0)
|
||||
.plusSeconds(second.getValue())
|
||||
.atZone(ZoneId.of("UTC+0"))
|
||||
|
||||
@ -22,7 +22,7 @@ import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
|
||||
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
|
||||
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
|
||||
import org.apache.doris.nereids.types.IntegerType;
|
||||
import org.apache.doris.nereids.types.BigIntType;
|
||||
import org.apache.doris.nereids.types.StringType;
|
||||
import org.apache.doris.nereids.types.VarcharType;
|
||||
|
||||
@ -38,9 +38,9 @@ public class FromUnixtime extends ScalarFunction
|
||||
implements ExplicitlyCastableSignature, AlwaysNullable {
|
||||
|
||||
public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
|
||||
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(IntegerType.INSTANCE),
|
||||
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(IntegerType.INSTANCE, VarcharType.SYSTEM_DEFAULT),
|
||||
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(IntegerType.INSTANCE, StringType.INSTANCE)
|
||||
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(BigIntType.INSTANCE),
|
||||
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(BigIntType.INSTANCE, VarcharType.SYSTEM_DEFAULT),
|
||||
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(BigIntType.INSTANCE, StringType.INSTANCE)
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@ -231,10 +231,11 @@ public class FEFunctions {
|
||||
return new IntLiteral(unixTime, Type.INT);
|
||||
}
|
||||
|
||||
@FEFunction(name = "from_unixtime", argTypes = { "INT" }, returnType = "VARCHAR")
|
||||
@FEFunction(name = "from_unixtime", argTypes = { "BIGINT" }, returnType = "VARCHAR")
|
||||
public static StringLiteral fromUnixTime(LiteralExpr unixTime) throws AnalysisException {
|
||||
// if unixTime < 0, we should return null, throw a exception and let BE process
|
||||
if (unixTime.getLongValue() < 0 || unixTime.getLongValue() >= Integer.MAX_VALUE) {
|
||||
// 32536771199L is max valid timestamp of mysql from_unix_time
|
||||
if (unixTime.getLongValue() < 0 || unixTime.getLongValue() > 32536771199L) {
|
||||
throw new AnalysisException("unix timestamp out of range");
|
||||
}
|
||||
DateLiteral dl = new DateLiteral(unixTime.getLongValue() * 1000, TimeUtils.getTimeZone(),
|
||||
@ -242,10 +243,11 @@ public class FEFunctions {
|
||||
return new StringLiteral(dl.getStringValue());
|
||||
}
|
||||
|
||||
@FEFunction(name = "from_unixtime", argTypes = { "INT", "VARCHAR" }, returnType = "VARCHAR")
|
||||
@FEFunction(name = "from_unixtime", argTypes = { "BIGINT", "VARCHAR" }, returnType = "VARCHAR")
|
||||
public static StringLiteral fromUnixTime(LiteralExpr unixTime, StringLiteral fmtLiteral) throws AnalysisException {
|
||||
// if unixTime < 0, we should return null, throw a exception and let BE process
|
||||
if (unixTime.getLongValue() < 0 || unixTime.getLongValue() >= Integer.MAX_VALUE) {
|
||||
// 32536771199L is max valid timestamp of mysql from_unix_time
|
||||
if (unixTime.getLongValue() < 0 || unixTime.getLongValue() >= 32536771199L) {
|
||||
throw new AnalysisException("unix timestamp out of range");
|
||||
}
|
||||
DateLiteral dl = new DateLiteral(unixTime.getLongValue() * 1000, TimeUtils.getTimeZone(),
|
||||
|
||||
@ -41,7 +41,7 @@ import java.util.function.Function;
|
||||
/*
|
||||
* rewrite sql: select * from table where from_unixtime(query_time) > '2021-03-02 12:12:23'
|
||||
* into: select * from table where query_time > 1614658343
|
||||
* query_time is integer type
|
||||
* query_time is big integer type to keep consistent with mysql
|
||||
* 1614658343 is the timestamp of 2021-03-02 12:12:23
|
||||
* this rewrite can improve the query performance, because from_unixtime is cpu-exhausted
|
||||
* */
|
||||
@ -115,7 +115,7 @@ public class RewriteFromUnixTimeRule implements ExprRewriteRule {
|
||||
return expr;
|
||||
}
|
||||
SlotRef sr = (SlotRef) paramSlot;
|
||||
if (!sr.getColumn().getType().isIntegerType()) {
|
||||
if (!sr.getColumn().getType().isBigIntType()) {
|
||||
return new BoolLiteral(false);
|
||||
}
|
||||
Expr right = bp.getChild(1);
|
||||
|
||||
Reference in New Issue
Block a user